From 6252951c52be7908fcb01f79af9ee39263faefbc Mon Sep 17 00:00:00 2001
From: Wes Gurney <wes.gurney@gmail.com>
Date: Fri, 30 Aug 2013 10:13:34 -0400
Subject: [PATCH 001/248] Added support to configure webhook_timeout in
 gitlab.yaml

---
 app/models/web_hook.rb            | 2 +-
 config/gitlab.yml.example         | 3 +++
 config/initializers/1_settings.rb | 1 +
 3 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/app/models/web_hook.rb b/app/models/web_hook.rb
index 3f22b1082fb..767d766a26a 100644
--- a/app/models/web_hook.rb
+++ b/app/models/web_hook.rb
@@ -17,7 +17,7 @@ class WebHook < ActiveRecord::Base
   attr_accessible :url
 
   # HTTParty timeout
-  default_timeout 10
+  default_timeout Gitlab.config.gitlab.webhook_timeout
 
   validates :url, presence: true,
                   format: { with: URI::regexp(%w(http https)), message: "should be a valid url" }
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 389dba59c9d..a9ab9092c67 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -58,6 +58,9 @@ production: &base
       wiki: true
       wall: false
       snippets: false
+	  
+    ## Webhook settings
+    # webhook_timeout: 30  # default: 10 - Number of seconds to wait for HTTP response after sending webhook HTTP POST request
 
   ## External issues trackers
   issues_tracker:
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index b3a19783b14..bfd6278dde8 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -70,6 +70,7 @@ Settings.gitlab['signup_enabled'] ||= false
 Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
 Settings.gitlab['issue_closing_pattern'] = '^([Cc]loses|[Ff]ixes) #(\d+)' if Settings.gitlab['issue_closing_pattern'].nil?
 Settings.gitlab['default_projects_features'] ||= {}
+Settings.gitlab['webhook_timeout'] ||= 10
 Settings.gitlab.default_projects_features['issues']         = true if Settings.gitlab.default_projects_features['issues'].nil?
 Settings.gitlab.default_projects_features['merge_requests'] = true if Settings.gitlab.default_projects_features['merge_requests'].nil?
 Settings.gitlab.default_projects_features['wiki']           = true if Settings.gitlab.default_projects_features['wiki'].nil?
-- 
GitLab


From 112e3b1c0fe52d0e2d357e09e4d3dc4e83303284 Mon Sep 17 00:00:00 2001
From: Wes Gurney <wes.gurney@gmail.com>
Date: Mon, 2 Sep 2013 21:20:39 -0400
Subject: [PATCH 002/248] Fixed default comments to make it clearer

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

diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index a9ab9092c67..7e1dacc5fa2 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -60,7 +60,8 @@ production: &base
       snippets: false
 	  
     ## Webhook settings
-    # webhook_timeout: 30  # default: 10 - Number of seconds to wait for HTTP response after sending webhook HTTP POST request
+    # Number of seconds to wait for HTTP response after sending webhook HTTP POST request (default: 10)
+    # webhook_timeout: 10
 
   ## External issues trackers
   issues_tracker:
-- 
GitLab


From 6b077c533e7037b7e2606fa287f1e57882154b32 Mon Sep 17 00:00:00 2001
From: Wes Gurney <wes.gurney@gmail.com>
Date: Fri, 4 Oct 2013 17:31:25 -0400
Subject: [PATCH 003/248] Cleaned comments

---
 config/initializers/1_settings.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index bfd6278dde8..a00768ed2d9 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -70,7 +70,7 @@ Settings.gitlab['signup_enabled'] ||= false
 Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
 Settings.gitlab['issue_closing_pattern'] = '^([Cc]loses|[Ff]ixes) #(\d+)' if Settings.gitlab['issue_closing_pattern'].nil?
 Settings.gitlab['default_projects_features'] ||= {}
-Settings.gitlab['webhook_timeout'] ||= 10
+Settings.gitlab['webhook_timeout'] ||= 10   
 Settings.gitlab.default_projects_features['issues']         = true if Settings.gitlab.default_projects_features['issues'].nil?
 Settings.gitlab.default_projects_features['merge_requests'] = true if Settings.gitlab.default_projects_features['merge_requests'].nil?
 Settings.gitlab.default_projects_features['wiki']           = true if Settings.gitlab.default_projects_features['wiki'].nil?
-- 
GitLab


From 43685b1b3c297004783442747261e194fe88ed0e Mon Sep 17 00:00:00 2001
From: Jonhnny Weslley <jw@jonhnnyweslley.net>
Date: Fri, 15 Feb 2013 16:35:03 -0300
Subject: [PATCH 004/248] add rake tasks for web hooks management

---
 lib/tasks/gitlab/web_hook.rake | 65 ++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)
 create mode 100644 lib/tasks/gitlab/web_hook.rake

diff --git a/lib/tasks/gitlab/web_hook.rake b/lib/tasks/gitlab/web_hook.rake
new file mode 100644
index 00000000000..f9f586db93c
--- /dev/null
+++ b/lib/tasks/gitlab/web_hook.rake
@@ -0,0 +1,65 @@
+namespace :gitlab do
+  namespace :web_hook do
+    desc "GITLAB | Adds a web hook to the projects"
+    task :add => :environment do
+      web_hook_url = ENV['URL']
+      namespace_path = ENV['NAMESPACE']
+
+      projects = find_projects(namespace_path)
+
+      puts "Adding web hook '#{web_hook_url}' to:"
+      projects.find_each(batch_size: 1000) do |project|
+        print "- #{project.name} ... "
+        web_hook = project.hooks.new(url: web_hook_url)
+        if web_hook.save
+          puts "added".green
+        else
+          print "failed".red
+          puts "  [#{web_hook.errors.full_messages.to_sentence}]"
+        end
+      end
+    end
+
+    desc "GITLAB | Remove a web hook from the projects"
+    task :rm => :environment do
+      web_hook_url = ENV['URL']
+      namespace_path = ENV['NAMESPACE']
+
+      projects = find_projects(namespace_path)
+      projects_ids = projects.pluck(:id)
+
+      puts "Removing web hooks with the url '#{web_hook_url}' ... "
+      count = WebHook.where(url: web_hook_url, project_id: projects_ids, type: 'ProjectHook').delete_all
+      puts "#{count} web hooks were removed."
+    end
+
+    desc "GITLAB | List web hooks"
+    task :list => :environment do
+      namespace_path = ENV['NAMESPACE']
+
+      projects = find_projects(namespace_path)
+      web_hooks = projects.all.map(&:hooks).flatten
+      web_hooks.each do |hook|
+        puts "#{hook.project.name.truncate(20).ljust(20)} -> #{hook.url}"
+      end
+
+      puts "\n#{web_hooks.size} web hooks found."
+    end
+  end
+
+  def find_projects(namespace_path)
+    if namespace_path.blank?
+      Project
+    elsif namespace_path == '/'
+      Project.where(namespace_id: nil)
+    else
+      namespace = Namespace.where(path: namespace_path).first
+      if namespace
+        Project.where(namespace_id: namespace.id)
+      else
+        puts "Namespace not found: #{namespace_path}".red
+        exit 2
+      end
+    end
+  end
+end
-- 
GitLab


From 5dc8dbe4087e568f99007fe34fc1712871825838 Mon Sep 17 00:00:00 2001
From: Jonhnny Weslley <jonhnny@credishop.com.br>
Date: Wed, 5 Jun 2013 11:32:22 -0300
Subject: [PATCH 005/248] add help page for web hooks management using rake
 tasks

---
 doc/raketasks/web_hooks.md | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 doc/raketasks/web_hooks.md

diff --git a/doc/raketasks/web_hooks.md b/doc/raketasks/web_hooks.md
new file mode 100644
index 00000000000..1ca5bacb9d1
--- /dev/null
+++ b/doc/raketasks/web_hooks.md
@@ -0,0 +1,31 @@
+### Add a web hook for **ALL** projects:
+
+    RAILS_ENV=production bundle exec rake gitlab:web_hook:add URL="http://example.com/hook"
+
+
+### Add a web hook for projects in a given **NAMESPACE**:
+
+    RAILS_ENV=production bundle exec rake gitlab:web_hook:add URL="http://example.com/hook" NAMESPACE=acme
+
+
+### Remove a web hook from **ALL** projects using:
+
+    RAILS_ENV=production bundle exec rake gitlab:web_hook:rm URL="http://example.com/hook"
+
+
+### Remove a web hook from projects in a given **NAMESPACE**:
+
+    RAILS_ENV=production bundle exec rake gitlab:web_hook:rm URL="http://example.com/hook" NAMESPACE=acme
+
+
+### List **ALL** web hooks:
+
+    RAILS_ENV=production bundle exec rake gitlab:web_hook:list
+
+
+### List the web hooks from projects in a given **NAMESPACE**:
+
+    RAILS_ENV=production bundle exec rake gitlab:web_hook:list NAMESPACE=/
+
+> Note: `/` is the global namespace.
+
-- 
GitLab


From 060abcb3b1fe8b3fb30aadc4855c8730356d731c Mon Sep 17 00:00:00 2001
From: Rovanion Luckey <rovanion.luckey@gmail.com>
Date: Sat, 17 Aug 2013 00:37:22 +0200
Subject: [PATCH 006/248] Remove -y option when removing puby1.8

Since it is easily could break installations running on the server - hence the person doing the install should be able to make the decision to remove himself.
---
 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 6523961d4d5..91dee7087f1 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -86,7 +86,7 @@ Then select 'Internet Site' and press enter to confirm the hostname.
 
 Remove the old Ruby 1.8 if present
 
-    sudo apt-get remove -y ruby1.8
+    sudo apt-get remove ruby1.8
 
 Download Ruby and compile it:
 
-- 
GitLab


From 515adbc41e43ae3f32217af9362bf5973201754d Mon Sep 17 00:00:00 2001
From: Rovanion <rovanion.luckey@gmail.com>
Date: Tue, 27 Aug 2013 13:30:06 +0200
Subject: [PATCH 007/248] Rewrote init script.

---
 CHANGELOG                 |   1 +
 lib/support/init.d/gitlab | 252 ++++++++++++++++++++++++++------------
 2 files changed, 175 insertions(+), 78 deletions(-)
 mode change 100644 => 100755 lib/support/init.d/gitlab

diff --git a/CHANGELOG b/CHANGELOG
index a6648d950b1..e843c180cd8 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,4 +1,5 @@
 v 6.1.0
+  - Rewrite: Init script now less prone to errors and keeps better track of the service.
   - Link issues, merge requests, and commits when they reference each other with GFM
   - Close issues automatically when pushing commits with a special message
   - Project internal ids for issues, mr, milestones
diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
old mode 100644
new mode 100755
index 6f97643f9e0..bf405c18cf9
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -1,7 +1,8 @@
-#! /bin/bash
+#! /bin/sh
 
 # GITLAB
 # Maintainer: @randx
+# Authors: rovanion.luckey@gmail.com, @randx
 # App Version: 6.0
 
 ### BEGIN INIT INFO
@@ -14,102 +15,198 @@
 # Description:       GitLab git repository management
 ### END INIT INFO
 
+### Environment variables
+RAILS_ENV="production"
 
-APP_ROOT="/home/git/gitlab"
-APP_USER="git"
-DAEMON_OPTS="-c $APP_ROOT/config/unicorn.rb -E production"
-PID_PATH="$APP_ROOT/tmp/pids"
-SOCKET_PATH="$APP_ROOT/tmp/sockets"
-WEB_SERVER_PID="$PID_PATH/unicorn.pid"
-SIDEKIQ_PID="$PID_PATH/sidekiq.pid"
-STOP_SIDEKIQ="RAILS_ENV=production bundle exec rake sidekiq:stop"
-START_SIDEKIQ="RAILS_ENV=production bundle exec rake sidekiq:start"
-NAME="gitlab"
-DESC="GitLab service"
-
-check_pid(){
-  if [ -f $WEB_SERVER_PID ]; then
-    PID=`cat $WEB_SERVER_PID`
-    SPID=`cat $SIDEKIQ_PID`
-    STATUS=`ps aux | grep $PID | grep -v grep | wc -l`
+# Script variable names should be lower-case not to conflict with internal
+# /bin/sh variables such as PATH, EDITOR or SHELL.
+app_root="/home/gitlab/gitlab"
+app_user="gitlab"
+unicorn_conf="$app_root/config/unicorn.rb"
+pid_path="$app_root/tmp/pids"
+socket_path="$app_root/tmp/sockets"
+web_server_pid_path="$pid_path/unicorn.pid"
+sidekiq_pid_path="$pid_path/sidekiq.pid"
+
+
+
+### Here ends user configuration ###
+
+
+# Switch to the app_user if it is not he/she who is running the script.
+if [ "$USER" != "$app_user" ]; then
+  sudo -u "$app_user" -H /etc/init.d/gitlab "$@"; exit;
+fi
+
+# Switch to the gitlab path, if it fails exit with an error.
+if ! cd "$app_root" ; then
+ echo "Failed to cd into $app_root, exiting!";  exit 1
+fi
+
+### Init Script functions
+
+check_pids(){
+  if ! mkdir -p "$pid_path"; then
+    echo "Could not create the path $pid_path needed to store the pids."
+    exit 1
+  fi
+  # If there exists a file which should hold the value of the Unicorn pid: read it.
+  if [ -f "$web_server_pid_path" ]; then
+    wpid=$(cat "$web_server_pid_path")
+  else
+    wpid=0
+  fi
+  if [ -f "$sidekiq_pid_path" ]; then
+    spid=$(cat "$sidekiq_pid_path")
   else
-    STATUS=0
-    PID=0
+    spid=0
   fi
 }
 
-execute() {
-  sudo -u $APP_USER -H bash -l -c "$1"
+# We use the pids in so many parts of the script it makes sense to always check them.
+# Only after start() is run should the pids change. Sidekiq sets it's own pid.
+check_pids
+
+
+# Checks wether the different parts of the server is already running or not.
+check_status(){
+  check_pids
+  # If the web server is running kill -0 $wpid returns true, or rather 0.
+  # Checks of *_status should only check for == 0 or != 0, never anything else.
+  if [ $wpid -ne 0 ]; then
+    kill -0 "$wpid" 2>/dev/null
+    web_status="$?"
+  fi
+  if [ $spid -ne 0 ]; then
+    kill -0 "$spid" 2>/dev/null
+    sidekiq_status="$?"
+  fi
 }
 
+# Check for stale pids and remove them if necessary
+check_stale_pids(){
+  check_status
+  # If there is a pid it is something else than 0, the service is running if
+  # *_status is == 0.
+  if [ "$wpid" != "0" -a "$web_status" != "0" ]; then
+    echo "Found stale Unicorn web server pid, removing. This is most likely caused by the web server crashing the last time it ran."
+    rm "$web_server_pid_path"
+  fi
+  if [ "$spid" != "0" -a "$sidekiq_status" != "0" ]; then
+    echo "Found stale Sidekiq web server pid, removing. This is most likely caused by the Sidekiq crashing the last time it ran."
+    rm "$sidekiq_pid_path"
+  fi
+}
+
+# If no parts of the service is running, bail out.
+check_not_running(){
+  check_stale_pids
+  if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then
+    echo "GitLab is not running."
+    exit
+  fi
+}
+
+# Starts Unicorn and Sidekiq.
 start() {
-  cd $APP_ROOT
-  check_pid
-  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
-    # Program is running, exit with error code 1.
-    echo "Error! $DESC $NAME is currently running!"
-    exit 1
+  check_stale_pids
+
+  # Then check if the service is running. If it is: don't start again.
+  if [ "$web_status" = "0" ]; then
+    echo "The Unicorn web server already running with pid $wpid, not restarting."
   else
-    if [ `whoami` = root ]; then
-      execute "rm -f $SOCKET_PATH/gitlab.socket"
-      execute "RAILS_ENV=production bundle exec unicorn_rails $DAEMON_OPTS  > /dev/null  2>&1 &"
-      execute "mkdir -p $PID_PATH && $START_SIDEKIQ  > /dev/null  2>&1 &"
-      echo "$DESC started"
-    fi
+    echo "Starting the GitLab Unicorn web server..."
+    # Remove old socket if it exists
+    rm -f "$socket_path"/gitlab.socket
+    # Start the webserver
+    bundle exec unicorn_rails -D -c "$unicorn_conf" -E "$RAILS_ENV"
   fi
-}
 
-stop() {
-  cd $APP_ROOT
-  check_pid
-  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
-    ## Program is running, stop it.
-    kill -QUIT `cat $WEB_SERVER_PID`
-    execute "mkdir -p $PID_PATH && $STOP_SIDEKIQ  > /dev/null  2>&1 &"
-    rm "$WEB_SERVER_PID" >> /dev/null
-    echo "$DESC stopped"
+  # If sidekiq is already running, don't start it again.
+  if [ "$sidekiq_status" = "0" ]; then
+    echo "The Sidekiq job dispatcher is already running with pid $spid, not restarting"
   else
-    ## Program is not running, exit with error.
-    echo "Error! $DESC not started!"
-    exit 1
+    echo "Starting the GitLab Sidekiq event dispatcher..."
+    RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start
+    # We are sleeping a bit here because sidekiq is slow at writing it's pid
+    sleep 2
   fi
+
+  # Finally check the status to tell wether or not GitLab is running
+  status
 }
 
-restart() {
-  cd $APP_ROOT
-  check_pid
-  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
-    echo "Restarting $DESC..."
-    kill -USR2 `cat $WEB_SERVER_PID`
-    execute "mkdir -p $PID_PATH && $STOP_SIDEKIQ  > /dev/null  2>&1"
-    if [ `whoami` = root ]; then
-      execute "mkdir -p $PID_PATH && $START_SIDEKIQ  > /dev/null  2>&1 &"
-    fi
-    echo "$DESC restarted."
+# Asks the Unicorn and the Sidekiq if they would be so kind as to stop, if not kills them.
+stop() {
+  check_not_running
+  # If the Unicorn web server is running, tell it to stop;
+  if [ "$web_status" = "0" ]; then
+    kill -QUIT "$wpid" &
+    echo "Stopping the GitLab Unicorn web server..."
+    stopping=true
   else
-    echo "Error, $NAME not running!"
-    exit 1
+    echo "The Unicorn web was not running, doing nothing."
+  fi
+  # And do the same thing for the Sidekiq.
+  if [ "$sidekiq_status" = "0" ]; then
+    printf "Stopping Sidekiq job dispatcher."
+    RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop &
+    stopping=true
+  else
+    echo "The Sidekiq was not running, must have run out of breath."
   fi
+
+
+  # If something needs to be stopped, lets wait for it to stop. Never use SIGKILL in a script.
+  while [ "$stopping" = "true" ]; do
+    sleep 1
+    check_status
+    if [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; then
+      printf "."
+    else
+      printf "\n"
+      break
+    fi
+  done
+  sleep 1
+  # Cleaning up unused pids
+  rm "$web_server_pid_path" 2>/dev/null
+  # rm "$sidekiq_pid_path" # Sidekiq seems to be cleaning up it's own pid.
+
+  status
 }
 
+# Returns the status of GitLab and it's components
 status() {
-  cd $APP_ROOT
-  check_pid
-  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
-    echo "$DESC / Unicorn with PID $PID is running."
-    echo "$DESC / Sidekiq with PID $SPID is running."
+  check_not_running
+  if [ "$web_status" = "0" ]; then
+      echo "The GitLab Unicorn webserver with pid $wpid is running."
   else
-    echo "$DESC is not running."
-    exit 1
+      printf "The GitLab Unicorn webserver is \033[31mnot running\033[0m.\n"
+  fi
+  if [ "$sidekiq_status" = "0" ]; then
+      echo "The GitLab Sidekiq job dispatcher with pid $spid is running."
+  else
+      printf "The GitLab Sidekiq job dispatcher is \033[31mnot running\033[0m.\n"
+  fi
+  if [ "$web_status" = "0" -a "$sidekiq_status" = "0" ]; then
+    printf "GitLab and all it's components are \033[32mup and running\033[0m.\n"
   fi
 }
 
-## Check to see if we are running as root first.
-## Found at http://www.cyberciti.biz/tips/shell-root-user-check-script.html
-if [ "$(id -u)" != "0" ]; then
-    echo "This script must be run as root"
+reload(){
+  check_not_running
+  if [ "$wpid" = "0" ];then
+    echo "The GitLab Unicorn Web server is not running thus it's configuration can't be reloaded."
     exit 1
-fi
+  fi
+  printf "Reloading GitLab configuration... "
+  kill -HUP "$wpid"
+  echo "Done."
+}
+
+
+## Finally the input handling.
 
 case "$1" in
   start)
@@ -119,20 +216,19 @@ case "$1" in
         stop
         ;;
   restart)
-        restart
+        stop
+	start
         ;;
   reload|force-reload)
-        echo -n "Reloading $NAME configuration: "
-        kill -HUP `cat $PID`
-        echo "done."
+	reload
         ;;
   status)
         status
         ;;
   *)
-        echo "Usage: sudo service gitlab {start|stop|restart|reload}" >&2
+        echo "Usage: service gitlab {start|stop|restart|reload|status}"
         exit 1
         ;;
 esac
 
-exit 0
+exit
\ No newline at end of file
-- 
GitLab


From 7ccb740dd23956a8d9c4c447dc2c404d4cc65b87 Mon Sep 17 00:00:00 2001
From: Rovanion <rovanion.luckey@gmail.com>
Date: Tue, 27 Aug 2013 15:04:20 +0200
Subject: [PATCH 008/248] Changes recommended by @axilleas

---
 lib/support/init.d/gitlab | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
index bf405c18cf9..65e036fe984 100755
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -20,8 +20,8 @@ RAILS_ENV="production"
 
 # Script variable names should be lower-case not to conflict with internal
 # /bin/sh variables such as PATH, EDITOR or SHELL.
-app_root="/home/gitlab/gitlab"
-app_user="gitlab"
+app_root="/home/git/gitlab"
+app_user="git"
 unicorn_conf="$app_root/config/unicorn.rb"
 pid_path="$app_root/tmp/pids"
 socket_path="$app_root/tmp/sockets"
@@ -68,7 +68,7 @@ check_pids(){
 check_pids
 
 
-# Checks wether the different parts of the server is already running or not.
+# Checks whether the different parts of the service are already running or not.
 check_status(){
   check_pids
   # If the web server is running kill -0 $wpid returns true, or rather 0.
@@ -117,7 +117,7 @@ start() {
   else
     echo "Starting the GitLab Unicorn web server..."
     # Remove old socket if it exists
-    rm -f "$socket_path"/gitlab.socket
+    rm -f "$socket_path"/gitlab.socket 2>/dev/null
     # Start the webserver
     bundle exec unicorn_rails -D -c "$unicorn_conf" -E "$RAILS_ENV"
   fi
@@ -231,4 +231,4 @@ case "$1" in
         ;;
 esac
 
-exit
\ No newline at end of file
+exit
-- 
GitLab


From 0d85f6a96211d3d903e25fd6d74aa040f5b31b25 Mon Sep 17 00:00:00 2001
From: Rovanion <rovanion.luckey@gmail.com>
Date: Wed, 28 Aug 2013 12:38:41 +0200
Subject: [PATCH 009/248] Corrections suggested by jacobvosmaer

---
 lib/support/init.d/gitlab | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
index 65e036fe984..eb9f5125c32 100755
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -20,8 +20,8 @@ RAILS_ENV="production"
 
 # Script variable names should be lower-case not to conflict with internal
 # /bin/sh variables such as PATH, EDITOR or SHELL.
-app_root="/home/git/gitlab"
-app_user="git"
+app_root="/home/gitlab/gitlab"
+app_user="gitlab"
 unicorn_conf="$app_root/config/unicorn.rb"
 pid_path="$app_root/tmp/pids"
 socket_path="$app_root/tmp/sockets"
@@ -99,7 +99,7 @@ check_stale_pids(){
 }
 
 # If no parts of the service is running, bail out.
-check_not_running(){
+exit_if_not_running(){
   check_stale_pids
   if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then
     echo "GitLab is not running."
@@ -138,7 +138,7 @@ start() {
 
 # Asks the Unicorn and the Sidekiq if they would be so kind as to stop, if not kills them.
 stop() {
-  check_not_running
+  exit_if_not_running
   # If the Unicorn web server is running, tell it to stop;
   if [ "$web_status" = "0" ]; then
     kill -QUIT "$wpid" &
@@ -178,7 +178,7 @@ stop() {
 
 # Returns the status of GitLab and it's components
 status() {
-  check_not_running
+  exit_if_not_running
   if [ "$web_status" = "0" ]; then
       echo "The GitLab Unicorn webserver with pid $wpid is running."
   else
@@ -195,14 +195,21 @@ status() {
 }
 
 reload(){
-  check_not_running
+  exit_if_not_running
   if [ "$wpid" = "0" ];then
     echo "The GitLab Unicorn Web server is not running thus it's configuration can't be reloaded."
     exit 1
   fi
-  printf "Reloading GitLab configuration... "
-  kill -HUP "$wpid"
+  printf "Reloading GitLab Unicorn configuration... "
+  kill -USR2 "$wpid"
   echo "Done."
+  echo "Restarting GitLab Sidekiq since it isn't capable of reloading it's config..."
+  RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop
+  echo "Starting Sidekiq..."  
+  RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start
+  # Waiting 2 seconds for sidekiq to write it.
+  sleep 2
+  status
 }
 
 
-- 
GitLab


From f0a3626675dd614dce5deb350ceb53a876804d2b Mon Sep 17 00:00:00 2001
From: Rovanion <rovanion.luckey@gmail.com>
Date: Wed, 28 Aug 2013 13:16:34 +0200
Subject: [PATCH 010/248] Fixed failure to stop and added handling of failure
 to remove stale pid

---
 lib/support/init.d/gitlab | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
index eb9f5125c32..00bd7a460c2 100755
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -20,8 +20,8 @@ RAILS_ENV="production"
 
 # Script variable names should be lower-case not to conflict with internal
 # /bin/sh variables such as PATH, EDITOR or SHELL.
-app_root="/home/gitlab/gitlab"
-app_user="gitlab"
+app_root="/home/git/gitlab"
+app_user="git"
 unicorn_conf="$app_root/config/unicorn.rb"
 pid_path="$app_root/tmp/pids"
 socket_path="$app_root/tmp/sockets"
@@ -76,10 +76,14 @@ check_status(){
   if [ $wpid -ne 0 ]; then
     kill -0 "$wpid" 2>/dev/null
     web_status="$?"
+  else
+    web_status="-1"
   fi
   if [ $spid -ne 0 ]; then
     kill -0 "$spid" 2>/dev/null
     sidekiq_status="$?"
+  else
+    sidekiq_status="-1"
   fi
 }
 
@@ -89,12 +93,18 @@ check_stale_pids(){
   # If there is a pid it is something else than 0, the service is running if
   # *_status is == 0.
   if [ "$wpid" != "0" -a "$web_status" != "0" ]; then
-    echo "Found stale Unicorn web server pid, removing. This is most likely caused by the web server crashing the last time it ran."
-    rm "$web_server_pid_path"
+    echo "Removing stale Unicorn web server pid. This is most likely caused by the web server crashing the last time it ran."
+    if ! rm "$web_server_pid_path"; then
+      echo "Unable to remove stale pid, exiting"
+      exit 1
+    fi
   fi
   if [ "$spid" != "0" -a "$sidekiq_status" != "0" ]; then
-    echo "Found stale Sidekiq web server pid, removing. This is most likely caused by the Sidekiq crashing the last time it ran."
-    rm "$sidekiq_pid_path"
+    echo "Removing stale Sidekiq web server pid. This is most likely caused by the Sidekiq crashing the last time it ran."
+    if ! rm "$sidekiq_pid_path"; then
+      echo "Unable to remove stale pid, exiting"
+      exit 1
+    fi
   fi
 }
 
@@ -205,7 +215,7 @@ reload(){
   echo "Done."
   echo "Restarting GitLab Sidekiq since it isn't capable of reloading it's config..."
   RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop
-  echo "Starting Sidekiq..."  
+  echo "Starting Sidekiq..."
   RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start
   # Waiting 2 seconds for sidekiq to write it.
   sleep 2
-- 
GitLab


From ecec03ee0ae1702e003cc733ebc985f7bcbeae68 Mon Sep 17 00:00:00 2001
From: Snooze- <derick@parallel.co.za>
Date: Thu, 29 Aug 2013 21:23:19 +0200
Subject: [PATCH 011/248] Create satellites during update to 6.0. Fix #4938
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Satellites for projects that were located in the root namespace needs to be recreated once they've been migrated to the creator’s namespace during the upgrade process.

This can be achieved by running the sudo -u git -H bundle exec rake gitlab:satellites:create RAILS_ENV=production during the update process.

The command has been added to the 5.4 to 6.0 update doc.
---
 doc/update/5.4-to-6.0.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md
index 0869dd833f9..907a134ed1d 100644
--- a/doc/update/5.4-to-6.0.md
+++ b/doc/update/5.4-to-6.0.md
@@ -70,6 +70,7 @@ sudo -u git -H bundle exec rake migrate_groups RAILS_ENV=production
 sudo -u git -H bundle exec rake migrate_global_projects RAILS_ENV=production
 sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production
 sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production
+sudo -u git -H bundle exec rake gitlab:satellites:create RAILS_ENV=production
 
 # Clear redis cache
 sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-- 
GitLab


From 1c85bcad5f0901e27a377ed93d09dca011cc0e62 Mon Sep 17 00:00:00 2001
From: Austin Robertson <austinrobertson@gmail.com>
Date: Thu, 29 Aug 2013 14:53:22 -0500
Subject: [PATCH 012/248] Add link to project page from admin view

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

diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 72317bb8efe..561d3252e22 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -12,7 +12,8 @@
       %ul.well-list
         %li
           %span.light Name:
-          %strong= @project.name
+          %strong
+            = link_to @project.name, project_path(@project)
         %li
           %span.light Namespace:
           %strong
-- 
GitLab


From 6daf8c41e9dd49d24e28741ea3a69042cef1dd99 Mon Sep 17 00:00:00 2001
From: Rovanion <rovanion.luckey@gmail.com>
Date: Thu, 29 Aug 2013 23:26:08 +0200
Subject: [PATCH 013/248] Restart works again, grammar mistakes corrected.

---
 lib/support/init.d/gitlab | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
index 00bd7a460c2..a05227ceb1b 100755
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -188,7 +188,11 @@ stop() {
 
 # Returns the status of GitLab and it's components
 status() {
-  exit_if_not_running
+  check_status
+  if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then
+    echo "GitLab is not running."
+    return
+  fi
   if [ "$web_status" = "0" ]; then
       echo "The GitLab Unicorn webserver with pid $wpid is running."
   else
@@ -207,13 +211,13 @@ status() {
 reload(){
   exit_if_not_running
   if [ "$wpid" = "0" ];then
-    echo "The GitLab Unicorn Web server is not running thus it's configuration can't be reloaded."
+    echo "The GitLab Unicorn Web server is not running thus its configuration can't be reloaded."
     exit 1
   fi
   printf "Reloading GitLab Unicorn configuration... "
   kill -USR2 "$wpid"
   echo "Done."
-  echo "Restarting GitLab Sidekiq since it isn't capable of reloading it's config..."
+  echo "Restarting GitLab Sidekiq since it isn't capable of reloading its config..."
   RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop
   echo "Starting Sidekiq..."
   RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start
@@ -222,6 +226,14 @@ reload(){
   status
 }
 
+restart(){
+  check_status
+  if [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; then
+    stop
+  fi
+  start
+}
+
 
 ## Finally the input handling.
 
@@ -233,8 +245,7 @@ case "$1" in
         stop
         ;;
   restart)
-        stop
-	start
+        restart
         ;;
   reload|force-reload)
 	reload
-- 
GitLab


From 5426a2801952f60808905725c6543491ea05e187 Mon Sep 17 00:00:00 2001
From: James Newton <james@Zaphyous.com>
Date: Thu, 29 Aug 2013 21:26:32 -0500
Subject: [PATCH 014/248] have email views use iid

---
 app/views/notify/closed_issue_email.html.haml             | 2 +-
 app/views/notify/closed_issue_email.text.haml             | 2 +-
 app/views/notify/closed_merge_request_email.html.haml     | 2 +-
 app/views/notify/closed_merge_request_email.text.haml     | 2 +-
 app/views/notify/issue_status_changed_email.html.haml     | 2 +-
 app/views/notify/issue_status_changed_email.text.erb      | 2 +-
 app/views/notify/merged_merge_request_email.html.haml     | 2 +-
 app/views/notify/merged_merge_request_email.text.haml     | 2 +-
 app/views/notify/new_issue_email.html.haml                | 2 +-
 app/views/notify/new_issue_email.text.erb                 | 4 ++--
 app/views/notify/new_merge_request_email.html.haml        | 2 +-
 app/views/notify/new_merge_request_email.text.erb         | 2 +-
 app/views/notify/new_user_email.text.erb                  | 2 +-
 app/views/notify/note_issue_email.html.haml               | 2 +-
 app/views/notify/note_issue_email.text.erb                | 2 +-
 app/views/notify/note_merge_request_email.html.haml       | 2 +-
 app/views/notify/note_merge_request_email.text.erb        | 6 +++---
 app/views/notify/note_wall_email.text.erb                 | 2 +-
 app/views/notify/project_was_moved_email.text.erb         | 4 ++--
 app/views/notify/reassigned_issue_email.html.haml         | 2 +-
 app/views/notify/reassigned_issue_email.text.erb          | 4 ++--
 app/views/notify/reassigned_merge_request_email.html.haml | 2 +-
 app/views/notify/reassigned_merge_request_email.text.erb  | 4 ++--
 23 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/app/views/notify/closed_issue_email.html.haml b/app/views/notify/closed_issue_email.html.haml
index 23ccc4538de..325cd44eb4b 100644
--- a/app/views/notify/closed_issue_email.html.haml
+++ b/app/views/notify/closed_issue_email.html.haml
@@ -1,5 +1,5 @@
 %p
   = "Issue was closed by #{@updated_by.name}"
 %p
-  = "Issue ##{@issue.id}"
+  = "Issue ##{@issue.iid}"
   = link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title
diff --git a/app/views/notify/closed_issue_email.text.haml b/app/views/notify/closed_issue_email.text.haml
index 0cca321552c..49f160a0d5f 100644
--- a/app/views/notify/closed_issue_email.text.haml
+++ b/app/views/notify/closed_issue_email.text.haml
@@ -1,3 +1,3 @@
 = "Issue was closed by #{@updated_by.name}"
 
-Issue ##{@issue.id}: #{project_issue_url(@issue.project, @issue)}
+Issue ##{@issue.iid}: #{project_issue_url(@issue.project, @issue)}
diff --git a/app/views/notify/closed_merge_request_email.html.haml b/app/views/notify/closed_merge_request_email.html.haml
index c6b45b1710a..45770cc85de 100644
--- a/app/views/notify/closed_merge_request_email.html.haml
+++ b/app/views/notify/closed_merge_request_email.html.haml
@@ -1,5 +1,5 @@
 %p
-  = "Merge Request #{@merge_request.id} was closed by #{@updated_by.name}"
+  = "Merge Request #{@merge_request.iid} was closed by #{@updated_by.name}"
 %p
   = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request)
 %p
diff --git a/app/views/notify/closed_merge_request_email.text.haml b/app/views/notify/closed_merge_request_email.text.haml
index 9a5bce5915a..ee434ec8cb2 100644
--- a/app/views/notify/closed_merge_request_email.text.haml
+++ b/app/views/notify/closed_merge_request_email.text.haml
@@ -1,4 +1,4 @@
-= "Merge Request #{@merge_request.id} was closed by #{@updated_by.name}"
+= "Merge Request #{@merge_request.iid} was closed by #{@updated_by.name}"
 
 Merge Request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
 
diff --git a/app/views/notify/issue_status_changed_email.html.haml b/app/views/notify/issue_status_changed_email.html.haml
index 4cdb70994ce..7706b3f7516 100644
--- a/app/views/notify/issue_status_changed_email.html.haml
+++ b/app/views/notify/issue_status_changed_email.html.haml
@@ -1,5 +1,5 @@
 %p
   = "Issue was #{@issue_status} by #{@updated_by.name}"
 %p
-  = "Issue ##{@issue.id}"
+  = "Issue ##{@issue.iid}"
   = link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title
diff --git a/app/views/notify/issue_status_changed_email.text.erb b/app/views/notify/issue_status_changed_email.text.erb
index bbca3474d50..4200881f7e8 100644
--- a/app/views/notify/issue_status_changed_email.text.erb
+++ b/app/views/notify/issue_status_changed_email.text.erb
@@ -1,4 +1,4 @@
 Issue was <%= @issue_status %> by <%= @updated_by.name %>
 
-Issue <%= @issue.id %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
+Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
 
diff --git a/app/views/notify/merged_merge_request_email.html.haml b/app/views/notify/merged_merge_request_email.html.haml
index e3ae41819f8..e2bc9cf5c04 100644
--- a/app/views/notify/merged_merge_request_email.html.haml
+++ b/app/views/notify/merged_merge_request_email.html.haml
@@ -1,5 +1,5 @@
 %p
-  = "Merge Request #{@merge_request.id} was merged"
+  = "Merge Request #{@merge_request.iid} was merged"
 %p
   = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request)
 %p
diff --git a/app/views/notify/merged_merge_request_email.text.haml b/app/views/notify/merged_merge_request_email.text.haml
index fa9ef0a4b32..550f677fed4 100644
--- a/app/views/notify/merged_merge_request_email.text.haml
+++ b/app/views/notify/merged_merge_request_email.text.haml
@@ -1,4 +1,4 @@
-= "Merge Request #{@merge_request.id} was merged"
+= "Merge Request #{@merge_request.iid} was merged"
 
 Merge Request Url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
 
diff --git a/app/views/notify/new_issue_email.html.haml b/app/views/notify/new_issue_email.html.haml
index f11c850641b..3b3c148517a 100644
--- a/app/views/notify/new_issue_email.html.haml
+++ b/app/views/notify/new_issue_email.html.haml
@@ -1,7 +1,7 @@
 %p
   New Issue was created.
 %p
-  = "Issue ##{@issue.id}"
+  = "Issue ##{@issue.iid}"
   = link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title
 %p
   Author: #{@issue.author_name}
diff --git a/app/views/notify/new_issue_email.text.erb b/app/views/notify/new_issue_email.text.erb
index 9907ca83247..d36f54eb1ca 100644
--- a/app/views/notify/new_issue_email.text.erb
+++ b/app/views/notify/new_issue_email.text.erb
@@ -1,5 +1,5 @@
 New Issue was created.
-          
-Issue <%= @issue.id %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
+
+Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
 Author:   <%= @issue.author_name %>
 Asignee:  <%= @issue.assignee_name %>
diff --git a/app/views/notify/new_merge_request_email.html.haml b/app/views/notify/new_merge_request_email.html.haml
index 3b060001e6b..6b2782ebb0b 100644
--- a/app/views/notify/new_merge_request_email.html.haml
+++ b/app/views/notify/new_merge_request_email.html.haml
@@ -1,5 +1,5 @@
 %p
-  = "New Merge Request !#{@merge_request.id}"
+  = "New Merge Request !#{@merge_request.iid}"
 %p
   = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request)
 %p
diff --git a/app/views/notify/new_merge_request_email.text.erb b/app/views/notify/new_merge_request_email.text.erb
index 3f711840a51..2d27350486e 100644
--- a/app/views/notify/new_merge_request_email.text.erb
+++ b/app/views/notify/new_merge_request_email.text.erb
@@ -1,4 +1,4 @@
-New Merge Request <%= @merge_request.id %>
+New Merge Request <%= @merge_request.iid %>
 
 <%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
 
diff --git a/app/views/notify/new_user_email.text.erb b/app/views/notify/new_user_email.text.erb
index 50ed595b38a..c21c95d3047 100644
--- a/app/views/notify/new_user_email.text.erb
+++ b/app/views/notify/new_user_email.text.erb
@@ -5,7 +5,7 @@ The Administrator created an account for you. Now you are a member of the compan
 login.................. <%= @user.email %>
 <% if @user.created_by_id %>
   password............... <%= @password %>
-  
+
   You will be forced to change this password immediately after login.
 <% end %>
 
diff --git a/app/views/notify/note_issue_email.html.haml b/app/views/notify/note_issue_email.html.haml
index ca1331260d3..b3230953e7d 100644
--- a/app/views/notify/note_issue_email.html.haml
+++ b/app/views/notify/note_issue_email.html.haml
@@ -1,4 +1,4 @@
 %p
-  = "New comment for Issue ##{@issue.id}"
+  = "New comment for Issue ##{@issue.iid}"
   = link_to_gfm truncate(@issue.title, length: 35), project_issue_url(@issue.project, @issue, anchor: "note_#{@note.id}")
 = render 'note_message'
diff --git a/app/views/notify/note_issue_email.text.erb b/app/views/notify/note_issue_email.text.erb
index a476b286ae4..8a61f54a337 100644
--- a/app/views/notify/note_issue_email.text.erb
+++ b/app/views/notify/note_issue_email.text.erb
@@ -1,4 +1,4 @@
-New comment for Issue <%= @issue.id %>
+New comment for Issue <%= @issue.iid %>
 
 <%= url_for(project_issue_url(@issue.project, @issue, anchor: "note_#{@note.id}")) %>
 
diff --git a/app/views/notify/note_merge_request_email.html.haml b/app/views/notify/note_merge_request_email.html.haml
index 14abcca6070..d587b068486 100644
--- a/app/views/notify/note_merge_request_email.html.haml
+++ b/app/views/notify/note_merge_request_email.html.haml
@@ -3,6 +3,6 @@
     = link_to "New comment on diff", diffs_project_merge_request_url(@merge_request.target_project, @merge_request, anchor: "note_#{@note.id}")
   - else
     = link_to "New comment", project_merge_request_url(@merge_request.target_project, @merge_request, anchor: "note_#{@note.id}")
-  for Merge Request ##{@merge_request.id}
+  for Merge Request ##{@merge_request.iid}
   %cite "#{truncate(@merge_request.title, length: 20)}"
 = render 'note_message'
diff --git a/app/views/notify/note_merge_request_email.text.erb b/app/views/notify/note_merge_request_email.text.erb
index 3daa091db81..79e72ca16c6 100644
--- a/app/views/notify/note_merge_request_email.text.erb
+++ b/app/views/notify/note_merge_request_email.text.erb
@@ -1,9 +1,9 @@
-New comment for Merge Request <%= @merge_request.id %>
+New comment for Merge Request <%= @merge_request.iid %>
 
 <%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request, anchor: "note_#{@note.id}")) %>
-      
+
 
 <%= @note.author_name %>
-                  
+
 <%= @note.note %>
 
diff --git a/app/views/notify/note_wall_email.text.erb b/app/views/notify/note_wall_email.text.erb
index 97910d5eb79..ee0dc3db1db 100644
--- a/app/views/notify/note_wall_email.text.erb
+++ b/app/views/notify/note_wall_email.text.erb
@@ -1,7 +1,7 @@
 New message on the project wall <%= @note.project %>
 
 <%= url_for(project_wall_url(@note.project, anchor: "note_#{@note.id}")) %>
-          
+
 
 <%= @note.author_name %>
 
diff --git a/app/views/notify/project_was_moved_email.text.erb b/app/views/notify/project_was_moved_email.text.erb
index 9c41073fddc..7889c7b9cc4 100644
--- a/app/views/notify/project_was_moved_email.text.erb
+++ b/app/views/notify/project_was_moved_email.text.erb
@@ -1,8 +1,8 @@
 Project was moved to another location
-          
+
 The project is now located under 
 <%= project_url(@project) %>
-          
+
 
 To update the remote url in your local repository run:
   git remote set-url origin <%= @project.ssh_url_to_repo %>
diff --git a/app/views/notify/reassigned_issue_email.html.haml b/app/views/notify/reassigned_issue_email.html.haml
index 6d332af3d70..b0edff44ce6 100644
--- a/app/views/notify/reassigned_issue_email.html.haml
+++ b/app/views/notify/reassigned_issue_email.html.haml
@@ -1,5 +1,5 @@
 %p
-  = "Reassigned Issue ##{@issue.id}"
+  = "Reassigned Issue ##{@issue.iid}"
   = link_to_gfm truncate(@issue.title, length: 30), project_issue_url(@issue.project, @issue)
 %p
   Assignee changed
diff --git a/app/views/notify/reassigned_issue_email.text.erb b/app/views/notify/reassigned_issue_email.text.erb
index 867c4d01da5..bc0d0567922 100644
--- a/app/views/notify/reassigned_issue_email.text.erb
+++ b/app/views/notify/reassigned_issue_email.text.erb
@@ -1,5 +1,5 @@
-Reassigned Issue <%= @issue.id %>
+Reassigned Issue <%= @issue.iid %>
 
 <%= url_for(project_issue_url(@issue.project, @issue)) %>
-          
+
 Assignee changed <%= "from #{@previous_assignee.name}" if @previous_assignee %> to <%= @issue.assignee_name %>
diff --git a/app/views/notify/reassigned_merge_request_email.html.haml b/app/views/notify/reassigned_merge_request_email.html.haml
index 314b2882672..3a615f86e69 100644
--- a/app/views/notify/reassigned_merge_request_email.html.haml
+++ b/app/views/notify/reassigned_merge_request_email.html.haml
@@ -1,5 +1,5 @@
 %p
-  = "Reassigned Merge Request !#{@merge_request.id}"
+  = "Reassigned Merge Request !#{@merge_request.iid}"
   = link_to_gfm truncate(@merge_request.title, length: 30), project_merge_request_url(@merge_request.target_project, @merge_request)
 %p
   Assignee changed
diff --git a/app/views/notify/reassigned_merge_request_email.text.erb b/app/views/notify/reassigned_merge_request_email.text.erb
index 05a9797165d..eecf055ff6f 100644
--- a/app/views/notify/reassigned_merge_request_email.text.erb
+++ b/app/views/notify/reassigned_merge_request_email.text.erb
@@ -1,7 +1,7 @@
-Reassigned Merge Request <%= @merge_request.id %>
+Reassigned Merge Request <%= @merge_request.iid %>
 
 <%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
-          
+
 
 Assignee changed <%= "from #{@previous_assignee.name}" if @previous_assignee %> to <%= @merge_request.assignee_name %>
 
-- 
GitLab


From 99341201bf49edf057f3e15ffe86e5a0406998c7 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 30 Aug 2013 17:10:58 +0300
Subject: [PATCH 015/248] Rename team to Project members

---
 app/views/admin/projects/show.html.haml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 561d3252e22..4544a9aa190 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -78,8 +78,8 @@
     - if @group
       .ui-box
         .title
-          %strong #{@group.name} Group
-          members (#{@group.users_groups.count})
+          %strong #{@group.name}
+          group members (#{@group.users_groups.count})
           .pull-right
             = link_to admin_group_path(@group), class: 'btn btn-small' do
               %i.icon-edit
@@ -89,7 +89,7 @@
 
     .ui-box
       .title
-        Team
+        Project members
         %small
           (#{@project.users.count})
         .pull-right
-- 
GitLab


From 28c8da8b597f44c41dbf155828d53cb374629002 Mon Sep 17 00:00:00 2001
From: Johannes Schleifenbaum <johannes@js-webcoding.de>
Date: Fri, 30 Aug 2013 21:04:26 +0200
Subject: [PATCH 016/248] add missing comma(s) in api examples

---
 doc/api/deploy_keys.md |  6 +++---
 doc/api/session.md     |  2 +-
 doc/api/users.md       | 16 ++++++++--------
 3 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md
index 5a394094fe6..fbb1e45bccd 100644
--- a/doc/api/deploy_keys.md
+++ b/doc/api/deploy_keys.md
@@ -16,14 +16,14 @@ Parameters:
 [
   {
     "id": 1,
-    "title" : "Public key"
+    "title" : "Public key",
     "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
       596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
       soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
   },
   {
     "id": 3,
-    "title" : "Another Public key"
+    "title" : "Another Public key",
     "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
       596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
       soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
@@ -48,7 +48,7 @@ Parameters:
 ```json
 {
   "id": 1,
-  "title" : "Public key"
+  "title" : "Public key",
   "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
       596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
       soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
diff --git a/doc/api/session.md b/doc/api/session.md
index 8caf5fe1862..162d4c8bf78 100644
--- a/doc/api/session.md
+++ b/doc/api/session.md
@@ -27,7 +27,7 @@ __You can login with both GitLab and LDAP credentials now__
   "linkedin": "",
   "twitter": "",
   "dark_scheme": false,
-  "theme_id": 1
+  "theme_id": 1,
   "is_admin": false,
   "can_create_group" : true,
   "can_create_team" : true,
diff --git a/doc/api/users.md b/doc/api/users.md
index 20664f1e740..49afbab8c6a 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -22,7 +22,7 @@ GET /users
     "twitter": "",
     "extern_uid": "john.smith",
     "provider": "provider_name",
-    "theme_id": 1
+    "theme_id": 1,
     "color_scheme_id": 2
   },
   {
@@ -38,7 +38,7 @@ GET /users
     "twitter": "",
     "extern_uid": "jack.smith",
     "provider": "provider_name",
-    "theme_id": 1
+    "theme_id": 1,
     "color_scheme_id": 3
   }
 ]
@@ -71,7 +71,7 @@ Parameters:
   "twitter": "",
   "extern_uid": "john.smith",
   "provider": "provider_name",
-  "theme_id": 1
+  "theme_id": 1,
   "color_scheme_id": 2
 }
 ```
@@ -162,8 +162,8 @@ GET /user
   "skype": "",
   "linkedin": "",
   "twitter": "",
-  "theme_id": 1
-  "color_scheme_id": 2
+  "theme_id": 1,
+  "color_scheme_id": 2,
   "is_admin": false,
   "can_create_group" : true,
   "can_create_team" : true,
@@ -184,14 +184,14 @@ GET /user/keys
 [
   {
     "id": 1,
-    "title" : "Public key"
+    "title" : "Public key",
     "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
       596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
       soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
   },
   {
     "id": 3,
-    "title" : "Another Public key"
+    "title" : "Another Public key",
     "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
       596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
       soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
@@ -219,7 +219,7 @@ Parameters:
 ```json
 {
   "id": 1,
-  "title" : "Public key"
+  "title" : "Public key",
   "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
       596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
       soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
-- 
GitLab


From 3f918e3202fd9d804968ea60bff952790052270b Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 1 Sep 2013 01:04:22 +0300
Subject: [PATCH 017/248] Use original raphael-rails v2.1.2

---
 Gemfile      | 2 +-
 Gemfile.lock | 9 ++-------
 db/schema.rb | 4 ++--
 3 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/Gemfile b/Gemfile
index c80705af316..5b8118457d3 100644
--- a/Gemfile
+++ b/Gemfile
@@ -134,7 +134,7 @@ group :assets do
   gem "jquery-rails",     "2.1.3"
   gem "jquery-ui-rails",  "2.0.2"
   gem "modernizr",        "2.6.2"
-  gem "raphael-rails",    git: "https://github.com/gitlabhq/raphael-rails.git"
+  gem "raphael-rails", "~> 2.1.2"
   gem 'bootstrap-sass'
   gem "font-awesome-rails"
   gem "gemoji", "~> 1.2.1", require: 'emoji/railtie'
diff --git a/Gemfile.lock b/Gemfile.lock
index e608afad1e7..d71988e13e6 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -6,12 +6,6 @@ GIT
       activerecord (>= 2.3.0)
       rake (>= 0.8.7)
 
-GIT
-  remote: https://github.com/gitlabhq/raphael-rails.git
-  revision: cb2c92a040b9b941a5f1aa1ea866cc26e944fe58
-  specs:
-    raphael-rails (2.1.0)
-
 GEM
   remote: https://rubygems.org/
   specs:
@@ -380,6 +374,7 @@ GEM
       thor (>= 0.14.6, < 2.0)
     raindrops (0.11.0)
     rake (10.1.0)
+    raphael-rails (2.1.2)
     rb-fsevent (0.9.3)
     rb-inotify (0.9.0)
       ffi (>= 0.5.0)
@@ -611,7 +606,7 @@ DEPENDENCIES
   rails (= 3.2.13)
   rails-dev-tweaks
   rails_best_practices
-  raphael-rails!
+  raphael-rails (~> 2.1.2)
   rb-fsevent
   rb-inotify
   redcarpet (~> 2.2.2)
diff --git a/db/schema.rb b/db/schema.rb
index 5020230d831..654f2b1e8f7 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -144,8 +144,8 @@ ActiveRecord::Schema.define(:version => 20130821090531) do
     t.text     "note"
     t.string   "noteable_type"
     t.integer  "author_id"
-    t.datetime "created_at",    :null => false
-    t.datetime "updated_at",    :null => false
+    t.datetime "created_at",                       :null => false
+    t.datetime "updated_at",                       :null => false
     t.integer  "project_id"
     t.string   "attachment"
     t.string   "line_code"
-- 
GitLab


From 0ed0d84399c6d2661bc79087e9450871c9efb0a4 Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Sun, 1 Sep 2013 12:13:17 +0200
Subject: [PATCH 018/248] Refactor contributing process to make it more
 readable and make sure other core team members are mentioned.

---
 PROCESS.md | 72 ++++++++++++++++++++++++++++--------------------------
 1 file changed, 37 insertions(+), 35 deletions(-)

diff --git a/PROCESS.md b/PROCESS.md
index 17684ae5c71..a7a61c5231a 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -2,23 +2,47 @@
 
 ## Purpose of describing the contributing process
 
-Below we describe the contributing process for two reasons. Contributors know what to expect from maintainers (initial, response within xx days, friendly treatment, etc). And maintainers know what to expect from contributors (use latest version, confirm the issue is addressed, friendly treatment, etc).
+Below we describe the contributing process to GitLab for two reasons. So that contributors know what to expect from maintainers (possible responses, friendly treatment, etc.). And so that maintainers know what to expect from contributors (use the latest version, ensure that the issue is addressed, friendly treatment, etc.).
 
-## How we handle issues
+## Common actions
 
-The priority should be mentioning people that can help and assigning workflow labels. Workflow labels are purposely not very detailed since that would be hard to keep updated as you would need to reevaluate them after every comment. We optionally use functional labels on demand when want to group related issues to get an overview (for example all issues related to RVM, to tackle them in one go) and to add details to the issue. 
+### Issue team
+- Looks for issues without workflow labels and triages issue
+- Monitors pull requests
+- Closes invalid issues and pull requests with a comment (duplicates, [feature requests](#feature-requests), [fixed in newer version](#issue-fixed-in-newer-version), [issue report for old version](#issue-report-for-old-version), not a problem in GitLab, etc.)
+- Assigns appropriate [labels](#how-we-handle-issues)
+- Asks for feedback from issue reporter/pull request initiator ([invalid issue reports](#improperly-formatted-issue), [format code](#code-format), etc.)
+- Asks for feedback from the relevant developer(s) based on the [list of members and their specialities](http://gitlab.org/team/)
+- Monitors all issues/pull requests for feedback (but especially ones commented on since automatically watching them):
+- Closes issues with no feedback from the reporter for two weeks
+- Closes stale pull requests
 
-If an issue is complex and needs the attention of a specific person, assignment is a good option but assigning issues might discourage other people from contributing to that issue. We need all the contributions we can get so this should never be discouraged. Also, an assigned person might not have time for a few weeks, so others should feel free to takeover. 
+### Development team
 
-Priority (from high to low):
+- Responds to issues and pull requests the issue team mentions them in
+- Monitors for new issues in _Awaiting developer action/feedback_ with no developer activity (once a week)
+- Monitors for new pull requests (at least once a week)
+- Manages their work queue by looking at issues and pull requests assigned to them
+- Close fixed issues (via commit messages or manually)
+- Codes [new features](http://feedback.gitlab.com/forums/176466-general/filters/top)!
+- Response guidelines
+- Be kind to people trying to contribute. Be aware that people can be a non-native or a native English speaker, they might not understand thing or they might be very sensitive to how your word things. Use emoji to express your feelings (hearth, star, smile, etc.). Some good tips about giving feedback to pull requests is in the [Thoughtbot code review guide](https://github.com/thoughtbot/guides/tree/master/code-review).
+
+## Priorities of the issue team
+
+1. Mentioning people (critical)
+2. Workflow labels (normal)
+3. Functional labels (minor)
+4. Assigning issues (avoid if possible)
 
-1. Mentioning people (very important)
-2. Workflow labels
-3. Functional labels (less important)
-4. Assigning issues (optional)
+## Mentioning people
+
+The most important thing is making sure valid issues receive feedback from the development team. Therefore the priority is mentioning developers that can help on those issue. Please select someone with relevant experience from [GitLab core team](http://gitlab.org/team/). If there is nobody mentioned with that expertise look in the commit history for the affected files to find someone. Avoid mentioning the lead developer, this is the person that is least likely to give a timely response. If the involvement of the lead developer is needed the other core team members will mention this person.
 
 ## Workflow labels
 
+Workflow labels are purposely not very detailed since that would be hard to keep updated as you would need to reevaluate them after every comment. We optionally use functional labels on demand when want to group related issues to get an overview (for example all issues related to RVM, to tackle them in one go) and to add details to the issue. 
+
 - _Awaiting feedback_: Feedback pending from the reporter
 - _Awaiting confirmation of fix_: The issue should already be solved in **master** (generally you can avoid this workflow item and just close the issue right away)
 - _Attached PR_: There is a PR attached and the discussion should happen there
@@ -29,6 +53,10 @@ Priority (from high to low):
 
 These labels describe what development specialities are involved such as: PostgreSQL, UX, LDAP.
 
+## Assigning issues
+
+If an issue is complex and needs the attention of a specific person, assignment is a good option but assigning issues might discourage other people from contributing to that issue. We need all the contributions we can get so this should never be discouraged. Also, an assigned person might not have time for a few weeks, so others should feel free to takeover.
+
 ## Label colors
 - Light orange `#fef2c0`: workflow labels for issue team members (awaiting feedback, awaiting confirmation of fix)
 - Bright orange `#eb6420`: workflow labels for core team members (attached PR, awaiting developer action/feedback)
@@ -37,32 +65,6 @@ These labels describe what development specialities are involved such as: Postgr
   - Feature request (see copy & paste response: [Feature requests](#feature-requests))
   - Support (see copy & paste response: [Support requests and configuration questions](#support-requests-and-configuration-questions)
 
-## Common actions
-
-### Issue team
-- Looks for issues without workflow labels and triages issue
-- Monitors pull requests
-- Closes invalid issues and pull requests with a comment (duplicates, [feature requests](#feature-requests), [fixed in newer version](#issue-fixed-in-newer-version), [issue report for old version](#issue-report-for-old-version), not a problem in GitLab, etc.)
-- Assigns appropriate [labels](#how-we-handle-issues)
-- Asks for feedback from issue reporter/pull request initiator ([invalid issue reports](#improperly-formatted-issue), [format code](#code-format), etc.)
-- Asks for feedback from the relevant developer(s) based on the [list of members and their specialities](http://gitlab.org/team/)
-- Monitors all issues/pull requests for feedback (but especially ones commented on since automatically watching them):
-- Assigns issues to developers if they indicate they are fixing it
-- Assigns pull requests to developers if they indicate they will take care of merge
-- Closes issues with no feedback from the reporter for two weeks
-- Closes stale pull requests
-
-### Development team
-
-- Responds to issues and pull requests the issue team mentions them in
-- Monitors for new issues in _Awaiting developer action/feedback_ with no developer activity (once a week)
-- Monitors for new pull requests (at least once a week)
-- Manages their work queue by looking at issues and pull requests assigned to them
-- Close fixed issues (via commit messages or manually)
-- Codes [new features](http://feedback.gitlab.com/forums/176466-general/filters/top)!
-- Response guidelines
-- Be kind to people trying to contribute. Be aware that people can be a non-native or a native English speaker, they might not understand thing or they might be very sensitive to how your word things. Use emoji to express your feelings (hearth, star, smile, etc.). Some good tips about giving feedback to pull requests is in the [Thoughtbot code review guide](https://github.com/thoughtbot/guides/tree/master/code-review).
-
 ## Copy & paste responses
 
 ### Improperly formatted issue
-- 
GitLab


From 408fa05edf5ba055c996f9e2620faeaa0796fe66 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 1 Sep 2013 22:07:02 +0300
Subject: [PATCH 019/248] Color in .rspec

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

diff --git a/.rspec b/.rspec
index 5902dd3af1f..7488cbe7792 100644
--- a/.rspec
+++ b/.rspec
@@ -1 +1 @@
---colour --drb
+--color --drb
-- 
GitLab


From ae1b3879895b5421ab5dae1433039bb615fe9a71 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 2 Sep 2013 23:35:40 +0300
Subject: [PATCH 020/248] Mode User+LDAP functionality from Gitlab::Auth

---
 .../omniauth_callbacks_controller.rb          | 12 +--
 app/models/user.rb                            |  1 +
 lib/gitlab/auth.rb                            | 17 ----
 lib/gitlab/ldap/user.rb                       | 92 +++++++++++++++++++
 4 files changed, 99 insertions(+), 23 deletions(-)
 create mode 100644 lib/gitlab/ldap/user.rb

diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index c4ebf0e4889..b0765672dda 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -16,12 +16,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
   end
 
   def ldap
-    # We only find ourselves here if the authentication to LDAP was successful.
-    @user = User.find_for_ldap_auth(request.env["omniauth.auth"], current_user)
-    if @user.persisted?
-      @user.remember_me = true
-    end
-    sign_in_and_redirect @user
+    # We only find ourselves here
+    # if the authentication to LDAP was successful.
+    @user = Gitlab::LDAP::User.find_or_create(request.env["omniauth.auth"])
+    @user.remember_me = true if @user.persisted?
+
+    sign_in_and_redirect(@user)
   end
 
   private
diff --git a/app/models/user.rb b/app/models/user.rb
index b44c063c32f..823e7a24a25 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -159,6 +159,7 @@ class User < ActiveRecord::Base
   scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) }
   scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : scoped }
   scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)') }
+  scope :ldap, -> { where(provider:  'ldap') }
 
   scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active  }
 
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index de70c5ce780..5f4b6c22c2c 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -13,23 +13,6 @@ module Gitlab
       end
     end
 
-    def find_for_ldap_auth(auth, signed_in_resource = nil)
-      uid = auth.info.uid
-      provider = auth.provider
-      email = auth.info.email.downcase unless auth.info.email.nil?
-      raise OmniAuth::Error, "LDAP accounts must provide an uid and email address" if uid.nil? or email.nil?
-
-      if @user = User.find_by_extern_uid_and_provider(uid, provider)
-        @user
-      elsif @user = User.find_by_email(email)
-        log.info "Updating legacy LDAP user #{email} with extern_uid => #{uid}"
-        @user.update_attributes(extern_uid: uid, provider: provider)
-        @user
-      else
-        create_from_omniauth(auth, true)
-      end
-    end
-
     def create_from_omniauth(auth, ldap = false)
       provider = auth.provider
       uid = auth.info.uid || auth.uid
diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
new file mode 100644
index 00000000000..a7a11e5a640
--- /dev/null
+++ b/lib/gitlab/ldap/user.rb
@@ -0,0 +1,92 @@
+# LDAP extension for User model
+#
+# * Find or create user from omniauth.auth data
+# * Links LDAP account with existing user
+#
+module Gitlab
+  module LDAP
+    class User
+      class << self
+        def find(uid, email)
+          # Look for user with ldap provider and same uid
+          user = model.ldap.where(extern_uid: uid).last
+          return user if user
+
+          # Look for user with same emails
+          #
+          # Possible cases:
+          # * When user already has account and need to link his LDAP account.
+          # * LDAP uid changed for user with same email and we need to update his uid
+          #
+          user = model.find_by_email(email)
+
+          if user
+            user.update_attributes(extern_uid: uid, provider: 'ldap')
+            log.info("(LDAP) Updating legacy LDAP user #{email} with extern_uid => #{uid}")
+          end
+
+          user
+        end
+
+        def create(uid, email, name)
+          password = Devise.friendly_token[0, 8].downcase
+          username = email.match(/^[^@]*/)[0]
+
+          opts = {
+            extern_uid: uid,
+            provider: 'ldap',
+            name: name,
+            username: username,
+            email: email,
+            password: password,
+            password_confirmation: password,
+          }
+
+          user = model.new(opts, as: :admin).with_defaults
+          user.save!
+          log.info "(LDAP) Creating user #{email} from login with extern_uid => #{uid}"
+
+          user
+        end
+
+        def find_or_create(auth)
+          uid, email, name = uid(auth), email(auth), name(auth)
+
+          if uid.blank? || email.blank?
+            raise_error("Account must provide an uid and email address")
+          end
+
+          user = find(uid, email)
+          user = create(uid, email, name) unless user
+          user
+        end
+
+        private
+
+        def uid(auth)
+          auth.info.uid
+        end
+
+        def email(auth)
+          auth.info.email.downcase unless auth.info.email.nil?
+        end
+
+        def name(auth)
+          auth.info.name.to_s.force_encoding("utf-8")
+        end
+
+        def log
+          Gitlab::AppLogger
+        end
+
+        def raise_error(message)
+          raise OmniAuth::Error, "(LDAP) " + message
+        end
+
+        def model
+          ::User
+        end
+      end
+    end
+  end
+end
-- 
GitLab


From 69a0d19881a6c5ddd33cf0e2d7f7856776faaaf5 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 2 Sep 2013 23:50:45 +0300
Subject: [PATCH 021/248] Move ldap auth to LDAP::User. Removed unused code

---
 lib/gitlab/auth.rb               | 19 ++++---------------
 lib/gitlab/backend/grack_ldap.rb | 24 ------------------------
 lib/gitlab/ldap/user.rb          | 25 ++++++++++++++++++++++++-
 3 files changed, 28 insertions(+), 40 deletions(-)
 delete mode 100644 lib/gitlab/backend/grack_ldap.rb

diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 5f4b6c22c2c..34e25bc9ccb 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -66,23 +66,12 @@ module Gitlab
       Gitlab::AppLogger
     end
 
-    def ldap_auth(login, password)
-      # Check user against LDAP backend if user is not authenticated
-      # Only check with valid login and password to prevent anonymous bind results
-      return nil unless ldap_conf.enabled && !login.blank? && !password.blank?
-
-      ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
-      ldap_user = ldap.bind_as(
-        filter: Net::LDAP::Filter.eq(ldap.uid, login),
-        size: 1,
-        password: password
-      )
-
-      User.find_by_extern_uid_and_provider(ldap_user.dn, 'ldap') if ldap_user
-    end
-
     def ldap_conf
       @ldap_conf ||= Gitlab.config.ldap
     end
+
+    def ldap_auth(login, password)
+      Gitlab::LDAP::User.auth(login, password)
+    end
   end
 end
diff --git a/lib/gitlab/backend/grack_ldap.rb b/lib/gitlab/backend/grack_ldap.rb
deleted file mode 100644
index 45e98fbac1e..00000000000
--- a/lib/gitlab/backend/grack_ldap.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-require 'omniauth-ldap'
-
-module Grack
-  module LDAP
-    def ldap_auth(login, password)
-      # Check user against LDAP backend if user is not authenticated
-      # Only check with valid login and password to prevent anonymous bind results
-      return nil unless ldap_conf.enabled && !login.blank? && !password.blank?
-
-      ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
-      ldap_user = ldap.bind_as(
-        filter: Net::LDAP::Filter.eq(ldap.uid, login),
-        size: 1,
-        password: password
-      )
-
-      User.find_by_extern_uid_and_provider(ldap_user.dn, 'ldap') if ldap_user
-    end
-
-    def ldap_conf
-      @ldap_conf ||= Gitlab.config.ldap
-    end
-  end
-end
diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
index a7a11e5a640..fe4a93f3fe7 100644
--- a/lib/gitlab/ldap/user.rb
+++ b/lib/gitlab/ldap/user.rb
@@ -9,7 +9,7 @@ module Gitlab
       class << self
         def find(uid, email)
           # Look for user with ldap provider and same uid
-          user = model.ldap.where(extern_uid: uid).last
+          user = find_by_uid(uid)
           return user if user
 
           # Look for user with same emails
@@ -61,6 +61,25 @@ module Gitlab
           user
         end
 
+        def find_by_uid(uid)
+          model.ldap.where(extern_uid: uid).last
+        end
+
+        def auth(login, password)
+          # Check user against LDAP backend if user is not authenticated
+          # Only check with valid login and password to prevent anonymous bind results
+          return nil unless ldap_conf.enabled && login.present? && password.present?
+
+          ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
+          ldap_user = ldap.bind_as(
+            filter: Net::LDAP::Filter.eq(ldap.uid, login),
+            size: 1,
+            password: password
+          )
+
+          find_by_uid(ldap_user.dn) if ldap_user
+        end
+
         private
 
         def uid(auth)
@@ -86,6 +105,10 @@ module Gitlab
         def model
           ::User
         end
+
+        def ldap_conf
+          Gitlab.config.ldap
+        end
       end
     end
   end
-- 
GitLab


From 20f30fddae2aa6427724e9ecdcbd5809a07576ce Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 2 Sep 2013 23:52:58 +0300
Subject: [PATCH 022/248] Remove include of grack_ldap

---
 lib/gitlab/backend/grack_auth.rb | 2 --
 1 file changed, 2 deletions(-)

diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb
index be5c58bb5a6..c522e0a413b 100644
--- a/lib/gitlab/backend/grack_auth.rb
+++ b/lib/gitlab/backend/grack_auth.rb
@@ -1,10 +1,8 @@
 require_relative 'shell_env'
-require_relative 'grack_ldap'
 require_relative 'grack_helpers'
 
 module Grack
   class Auth < Rack::Auth::Basic
-    include LDAP
     include Helpers
 
     attr_accessor :user, :project, :ref, :env
-- 
GitLab


From cfc1fc8dc7b7cf42dd1c978d88e8c6f1e99673df Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 3 Sep 2013 00:09:20 +0300
Subject: [PATCH 023/248] Use normal font-weight for file names on tree view

---
 app/assets/stylesheets/sections/tree.scss | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss
index b8b82bcf68c..850ed831dfb 100644
--- a/app/assets/stylesheets/sections/tree.scss
+++ b/app/assets/stylesheets/sections/tree.scss
@@ -15,6 +15,12 @@
   .tree-table {
     @include border-radius(0);
     .tree-item {
+      td {
+        padding: 8px 10px;
+        strong {
+          font-weight: normal;
+        }
+      }
       &:hover {
         td {
           background: $hover;
-- 
GitLab


From ca1cf8b193ea4262a36029bda7f82c09e1d26ab1 Mon Sep 17 00:00:00 2001
From: Robert Schilling <rschilling@student.tugraz.at>
Date: Tue, 3 Sep 2013 07:25:39 +0200
Subject: [PATCH 024/248] Add 'notes' to path blacklist, fixes #4967

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

diff --git a/lib/gitlab/blacklist.rb b/lib/gitlab/blacklist.rb
index 26f987b200c..2f9091e07df 100644
--- a/lib/gitlab/blacklist.rb
+++ b/lib/gitlab/blacklist.rb
@@ -3,7 +3,7 @@ module Gitlab
     extend self
 
     def path
-      %w(admin dashboard groups help profile projects search public assets u s teams merge_requests issues users snippets services repository hooks)
+      %w(admin dashboard groups help profile projects search public assets u s teams merge_requests issues users snippets services repository hooks notes)
     end
   end
 end
-- 
GitLab


From 63ab9c3a0769604db45200fab70ed2bdd00b5999 Mon Sep 17 00:00:00 2001
From: Rovanion <rovanion.luckey@gmail.com>
Date: Tue, 3 Sep 2013 14:24:20 +0200
Subject: [PATCH 025/248] Made script path flexible

---
 lib/support/init.d/gitlab | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
index a05227ceb1b..79c56a9854b 100755
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -35,7 +35,7 @@ sidekiq_pid_path="$pid_path/sidekiq.pid"
 
 # Switch to the app_user if it is not he/she who is running the script.
 if [ "$USER" != "$app_user" ]; then
-  sudo -u "$app_user" -H /etc/init.d/gitlab "$@"; exit;
+  sudo -u "$app_user" -H $0 "$@"; exit;
 fi
 
 # Switch to the gitlab path, if it fails exit with an error.
-- 
GitLab


From af49f2eb6f449d64e5f1104fe85406edf9379ec5 Mon Sep 17 00:00:00 2001
From: Robert Djurasaj <robert.djurasaj@gmail.com>
Date: Tue, 3 Sep 2013 09:09:12 -0600
Subject: [PATCH 026/248] Update installation docs to use v1.7.1 of
 gitlab-shell

---
 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 91dee7087f1..1f6b246b884 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -122,7 +122,7 @@ GitLab Shell is a ssh access and repository management software developed specia
     cd gitlab-shell
 
     # switch to right version
-    sudo -u git -H git checkout v1.7.0
+    sudo -u git -H git checkout v1.7.1
 
     sudo -u git -H cp config.yml.example config.yml
 
-- 
GitLab


From c9b068873c990e47d06838bef348211e8a6552d5 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 3 Sep 2013 20:55:01 +0300
Subject: [PATCH 027/248] Dont allow html render for RAW view

---
 app/controllers/projects/raw_controller.rb | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb
index 0d35f373e9c..0c23d411f4c 100644
--- a/app/controllers/projects/raw_controller.rb
+++ b/app/controllers/projects/raw_controller.rb
@@ -11,9 +11,17 @@ class Projects::RawController < Projects::ApplicationController
     @blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path)
 
     if @blob.exists?
+      type = if @blob.mime_type =~ /html|javascript/
+               'text/plain; charset=utf-8'
+             else
+               @blob.mime_type
+             end
+
+      headers['X-Content-Type-Options'] = 'nosniff'
+
       send_data(
         @blob.data,
-        type: @blob.mime_type,
+        type: type,
         disposition: 'inline',
         filename: @blob.name
       )
-- 
GitLab


From 41c8d39a41b2e8f902c630920c10ce98d2e4c96b Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 3 Sep 2013 23:58:42 +0300
Subject: [PATCH 028/248] Dont show remove user button for ldap user

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

diff --git a/app/views/profiles/account.html.haml b/app/views/profiles/account.html.haml
index d711d55ec99..42214a1b46f 100644
--- a/app/views/profiles/account.html.haml
+++ b/app/views/profiles/account.html.haml
@@ -86,7 +86,7 @@
         .controls
           = f.submit 'Save username', class: "btn btn-save"
 
-- if gitlab_config.signup_enabled
+- if gitlab_config.signup_enabled && !current_user.ldap_user?
   %fieldset.remove-account
     %legend
       Remove account
-- 
GitLab


From 51f67cbb353875985e05a13dd5800b89a4052eb9 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 4 Sep 2013 00:04:27 +0300
Subject: [PATCH 029/248] Added Gitlab::OAuth::User class

Authenticate or create users from OAuth providers
---
 lib/gitlab/oauth/user.rb | 85 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)
 create mode 100644 lib/gitlab/oauth/user.rb

diff --git a/lib/gitlab/oauth/user.rb b/lib/gitlab/oauth/user.rb
new file mode 100644
index 00000000000..515c5b769e5
--- /dev/null
+++ b/lib/gitlab/oauth/user.rb
@@ -0,0 +1,85 @@
+# OAuth extension for User model
+#
+# * Find GitLab user based on omniauth uid and provider
+# * Create new user from omniauth data
+#
+module Gitlab
+  module OAuth
+    class User
+      class << self
+        attr_reader :auth
+
+        def find(auth)
+          @auth = auth
+          find_by_uid_and_provider
+        end
+
+        def create(auth)
+          @auth = auth
+          password = Devise.friendly_token[0, 8].downcase
+          opts = {
+            extern_uid: uid,
+            provider: provider,
+            name: name,
+            username: username,
+            email: email,
+            password: password,
+            password_confirmation: password,
+          }
+
+          user = model.new(opts, as: :admin).with_defaults
+          user.save!
+          log.info "(OAuth) Creating user #{email} from login with extern_uid => #{uid}"
+
+          if Gitlab.config.omniauth['block_auto_created_users'] && !ldap?
+            user.block
+          end
+
+          user
+        end
+
+        private
+
+        def find_by_uid_and_provider
+          model.where(provider: provider, extern_uid: uid).last
+        end
+
+        def uid
+          auth.info.uid || auth.uid
+        end
+
+        def email
+          auth.info.email.downcase unless auth.info.email.nil?
+        end
+
+        def name
+          auth.info.name.to_s.force_encoding("utf-8")
+        end
+
+        def username
+          email.match(/^[^@]*/)[0]
+        end
+
+        def provider
+          auth.provider
+        end
+
+        def log
+          Gitlab::AppLogger
+        end
+
+        def model
+          ::User
+        end
+
+        def raise_error(message)
+          raise OmniAuth::Error, "(OAuth) " + message
+        end
+
+        def ldap?
+          provider == 'ldap'
+        end
+      end
+    end
+  end
+end
-- 
GitLab


From a987d93768c73f57d43082d1d9ec072157dbe226 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 4 Sep 2013 00:06:13 +0300
Subject: [PATCH 030/248] Inherit Gitlab::LDAP::User from Gitlab::OAuth::User

---
 lib/gitlab/ldap/user.rb | 100 +++++++++++++---------------------------
 1 file changed, 33 insertions(+), 67 deletions(-)

diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
index fe4a93f3fe7..c8f3a69376a 100644
--- a/lib/gitlab/ldap/user.rb
+++ b/lib/gitlab/ldap/user.rb
@@ -1,71 +1,49 @@
+require 'gitlab/oauth/user'
+
 # LDAP extension for User model
 #
 # * Find or create user from omniauth.auth data
 # * Links LDAP account with existing user
+# * Auth LDAP user with login and password
 #
 module Gitlab
   module LDAP
-    class User
+    class User < Gitlab::OAuth::User
       class << self
-        def find(uid, email)
-          # Look for user with ldap provider and same uid
-          user = find_by_uid(uid)
-          return user if user
-
-          # Look for user with same emails
-          #
-          # Possible cases:
-          # * When user already has account and need to link his LDAP account.
-          # * LDAP uid changed for user with same email and we need to update his uid
-          #
-          user = model.find_by_email(email)
-
-          if user
-            user.update_attributes(extern_uid: uid, provider: 'ldap')
-            log.info("(LDAP) Updating legacy LDAP user #{email} with extern_uid => #{uid}")
-          end
-
-          user
-        end
-
-        def create(uid, email, name)
-          password = Devise.friendly_token[0, 8].downcase
-          username = email.match(/^[^@]*/)[0]
-
-          opts = {
-            extern_uid: uid,
-            provider: 'ldap',
-            name: name,
-            username: username,
-            email: email,
-            password: password,
-            password_confirmation: password,
-          }
-
-          user = model.new(opts, as: :admin).with_defaults
-          user.save!
-          log.info "(LDAP) Creating user #{email} from login with extern_uid => #{uid}"
-
-          user
-        end
-
         def find_or_create(auth)
-          uid, email, name = uid(auth), email(auth), name(auth)
+          @auth = auth
 
           if uid.blank? || email.blank?
             raise_error("Account must provide an uid and email address")
           end
 
-          user = find(uid, email)
-          user = create(uid, email, name) unless user
-          user
-        end
+          user = find(auth)
+
+          unless user
+            # Look for user with same emails
+            #
+            # Possible cases:
+            # * When user already has account and need to link his LDAP account.
+            # * LDAP uid changed for user with same email and we need to update his uid
+            #
+            user = model.find_by_email(email)
+
+            if user
+              user.update_attributes(extern_uid: uid, provider: provider)
+              log.info("(LDAP) Updating legacy LDAP user #{email} with extern_uid => #{uid}")
+            else
+              # Create a new user inside GitLab database
+              # based on LDAP credentials
+              #
+              #
+              user = create(auth)
+            end
+          end
 
-        def find_by_uid(uid)
-          model.ldap.where(extern_uid: uid).last
+          user
         end
 
-        def auth(login, password)
+        def authenticate(login, password)
           # Check user against LDAP backend if user is not authenticated
           # Only check with valid login and password to prevent anonymous bind results
           return nil unless ldap_conf.enabled && login.present? && password.present?
@@ -82,30 +60,18 @@ module Gitlab
 
         private
 
-        def uid(auth)
-          auth.info.uid
-        end
-
-        def email(auth)
-          auth.info.email.downcase unless auth.info.email.nil?
-        end
-
-        def name(auth)
-          auth.info.name.to_s.force_encoding("utf-8")
+        def find_by_uid(uid)
+          model.where(provider: provider, extern_uid: uid).last
         end
 
-        def log
-          Gitlab::AppLogger
+        def provider
+          'ldap'
         end
 
         def raise_error(message)
           raise OmniAuth::Error, "(LDAP) " + message
         end
 
-        def model
-          ::User
-        end
-
         def ldap_conf
           Gitlab.config.ldap
         end
-- 
GitLab


From 9f5bd68ba20e2adaf9b3272fb12546ba56d31464 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 4 Sep 2013 00:06:29 +0300
Subject: [PATCH 031/248] Use new OAuth classes

---
 .../omniauth_callbacks_controller.rb          | 24 ++++++++++++-------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index b0765672dda..7131e0fe181 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -18,33 +18,39 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
   def ldap
     # We only find ourselves here
     # if the authentication to LDAP was successful.
-    @user = Gitlab::LDAP::User.find_or_create(request.env["omniauth.auth"])
+    @user = Gitlab::LDAP::User.find_or_create(oauth)
     @user.remember_me = true if @user.persisted?
-
     sign_in_and_redirect(@user)
   end
 
   private
 
   def handle_omniauth
-    oauth = request.env['omniauth.auth']
-    provider, uid = oauth['provider'], oauth['uid']
-
     if current_user
       # Change a logged-in user's authentication method:
-      current_user.extern_uid = uid
-      current_user.provider = provider
+      current_user.extern_uid = oauth['uid']
+      current_user.provider = oauth['provider']
       current_user.save
       redirect_to profile_path
     else
-      @user = User.find_or_new_for_omniauth(oauth)
+      @user = Gitlab::OAuth::User.find(oauth)
+
+      # Create user if does not exist
+      # and allow_single_sign_on is true
+      if Gitlab.config.omniauth['allow_single_sign_on']
+        @user ||= Gitlab::OAuth::User.create(oauth)
+      end
 
       if @user
-        sign_in_and_redirect @user
+        sign_in_and_redirect(@user)
       else
         flash[:notice] = "There's no such user!"
         redirect_to new_user_session_path
       end
     end
   end
+
+  def oauth
+    @oauth ||= request.env['omniauth.auth']
+  end
 end
-- 
GitLab


From cc31e524cee8708e34258cfcc36549c7e5df707d Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 4 Sep 2013 00:12:00 +0300
Subject: [PATCH 032/248] Refactor Gitlab::Auth

---
 app/models/user.rb | 16 --------------
 lib/gitlab/auth.rb | 55 +---------------------------------------------
 2 files changed, 1 insertion(+), 70 deletions(-)

diff --git a/app/models/user.rb b/app/models/user.rb
index 823e7a24a25..b593c22fde3 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -187,22 +187,6 @@ class User < ActiveRecord::Base
       end
     end
 
-    def create_from_omniauth(auth, ldap = false)
-      gitlab_auth.create_from_omniauth(auth, ldap)
-    end
-
-    def find_or_new_for_omniauth(auth)
-      gitlab_auth.find_or_new_for_omniauth(auth)
-    end
-
-    def find_for_ldap_auth(auth, signed_in_resource = nil)
-      gitlab_auth.find_for_ldap_auth(auth, signed_in_resource)
-    end
-
-    def gitlab_auth
-      Gitlab::Auth.new
-    end
-
     def search query
       where("name LIKE :query OR email LIKE :query OR username LIKE :query", query: "%#{query}%")
     end
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 34e25bc9ccb..0f196297477 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -7,61 +7,12 @@ module Gitlab
         # Second chance - try LDAP authentication
         return nil unless ldap_conf.enabled
 
-        ldap_auth(login, password)
+        Gitlab::LDAP::User.authenticate(login, password)
       else
         user if user.valid_password?(password)
       end
     end
 
-    def create_from_omniauth(auth, ldap = false)
-      provider = auth.provider
-      uid = auth.info.uid || auth.uid
-      uid = uid.to_s.force_encoding("utf-8")
-      name = auth.info.name.to_s.force_encoding("utf-8")
-      email = auth.info.email.to_s.downcase unless auth.info.email.nil?
-
-      ldap_prefix = ldap ? '(LDAP) ' : ''
-      raise OmniAuth::Error, "#{ldap_prefix}#{provider} does not provide an email"\
-        " address" if auth.info.email.blank?
-
-      log.info "#{ldap_prefix}Creating user from #{provider} login"\
-        " {uid => #{uid}, name => #{name}, email => #{email}}"
-      password = Devise.friendly_token[0, 8].downcase
-      @user = User.new({
-        extern_uid: uid,
-        provider: provider,
-        name: name,
-        username: email.match(/^[^@]*/)[0],
-        email: email,
-        password: password,
-        password_confirmation: password,
-      }, as: :admin).with_defaults
-      @user.save!
-
-      if Gitlab.config.omniauth['block_auto_created_users'] && !ldap
-        @user.block
-      end
-
-      @user
-    end
-
-    def find_or_new_for_omniauth(auth)
-      provider, uid = auth.provider, auth.uid
-      email = auth.info.email.downcase unless auth.info.email.nil?
-
-      if @user = User.find_by_provider_and_extern_uid(provider, uid)
-        @user
-      elsif @user = User.find_by_email(email)
-        @user.update_attributes(extern_uid: uid, provider: provider)
-        @user
-      else
-        if Gitlab.config.omniauth['allow_single_sign_on']
-          @user = create_from_omniauth(auth)
-          @user
-        end
-      end
-    end
-
     def log
       Gitlab::AppLogger
     end
@@ -69,9 +20,5 @@ module Gitlab
     def ldap_conf
       @ldap_conf ||= Gitlab.config.ldap
     end
-
-    def ldap_auth(login, password)
-      Gitlab::LDAP::User.auth(login, password)
-    end
   end
 end
-- 
GitLab


From fd0058357a37dd912f4f4578c9392e69bec998c2 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 4 Sep 2013 00:53:01 +0300
Subject: [PATCH 033/248] Improve Profile#account page

---
 app/helpers/profile_helper.rb        |  12 ++
 app/views/profiles/account.html.haml | 195 ++++++++++++++++-----------
 2 files changed, 128 insertions(+), 79 deletions(-)

diff --git a/app/helpers/profile_helper.rb b/app/helpers/profile_helper.rb
index 80d67009f59..88d9f184d0e 100644
--- a/app/helpers/profile_helper.rb
+++ b/app/helpers/profile_helper.rb
@@ -4,4 +4,16 @@ module ProfileHelper
       'active'
     end
   end
+
+  def show_profile_username_tab?
+    current_user.can_change_username?
+  end
+
+  def show_profile_social_tab?
+    Gitlab.config.omniauth.enabled && !current_user.ldap_user?
+  end
+
+  def show_profile_remove_tab?
+    Gitlab.config.gitlab.signup_enabled && !current_user.ldap_user?
+  end
 end
diff --git a/app/views/profiles/account.html.haml b/app/views/profiles/account.html.haml
index 42214a1b46f..8f43db66249 100644
--- a/app/views/profiles/account.html.haml
+++ b/app/views/profiles/account.html.haml
@@ -5,91 +5,128 @@
   - if current_user.ldap_user?
     Some options are unavailable for LDAP accounts
 %hr
-- unless current_user.ldap_user?
-  - if Gitlab.config.omniauth.enabled
-    %fieldset
-      %legend Social Accounts
-      .oauth_select_holder
-        %p.hint Tip: Click on icon to activate signin with one of the following services
-        - enabled_social_providers.each do |provider|
-          %span{class: oauth_active_class(provider) }
-            = link_to authbutton(provider, 32), omniauth_authorize_path(User, provider)
 
 
-  %fieldset.update-password
-    %legend Password
-    = form_for @user, url: update_password_profile_path, method: :put do |f|
-      .padded
-        %p.slead After a successful password update you will be redirected to login page where you should login with your new password
-        -if @user.errors.any?
-          .alert.alert-error
-            %ul
-              - @user.errors.full_messages.each do |msg|
-                %li= msg
+.row
+  .span2
+    %ul.nav.nav-pills.nav-stacked.nav-stacked-menu
+      %li.active
+        = link_to '#tab-token', 'data-toggle' => 'tab' do
+          Private Token
+      %li
+        = link_to '#tab-password', 'data-toggle' => 'tab' do
+          Password
 
-        .control-group
-          = f.label :password
-          .controls= f.password_field :password, required: true
-        .control-group
-          = f.label :password_confirmation
-          .controls
-            = f.password_field :password_confirmation, required: true
-        .control-group
-          .controls
-            = f.submit 'Save password', class: "btn btn-save"
+      - if show_profile_social_tab?
+        %li
+          = link_to '#tab-social', 'data-toggle' => 'tab' do
+            Social Accounts
 
+      - if show_profile_username_tab?
+        %li
+          = link_to '#tab-username', 'data-toggle' => 'tab' do
+            Change Username
 
+      - if show_profile_remove_tab?
+        %li
+          = link_to '#tab-remove', 'data-toggle' => 'tab' do
+            Remove Account
+  .span10
+    .tab-content
+      .tab-pane.active#tab-token
+        %fieldset.update-token
+          %legend
+            Private token
+            %span.cred.pull-right
+              keep it secret!
+          %div
+            = form_for @user, url: reset_private_token_profile_path, method: :put do |f|
+              .data
+                %p.slead
+                  Your private token is used to access application resources without authentication.
+                  %br
+                  It can be used for atom feeds or the API.
+                %p.cgray
+                  - if current_user.private_token
+                    = text_field_tag "token", current_user.private_token, class: "input-xxlarge large_text input-xpadding"
+                    = f.submit 'Reset', confirm: "Are you sure?", class: "btn btn-primary btn-build-token"
+                  - else
+                    %span You don`t have one yet. Click generate to fix it.
+                    = f.submit 'Generate', class: "btn success btn-build-token"
 
-%fieldset.update-token
-  %legend
-    Private token
-    %span.cred.pull-right
-      keep it secret!
-  .padded
-    = form_for @user, url: reset_private_token_profile_path, method: :put do |f|
-      .data
-        %p.slead
-          Your private token is used to access application resources without authentication.
-          %br
-          It can be used for atom feeds or the API.
-        %p.cgray
-          - if current_user.private_token
-            = text_field_tag "token", current_user.private_token, class: "input-xxlarge large_text input-xpadding"
-            = f.submit 'Reset', confirm: "Are you sure?", class: "btn btn-primary btn-build-token"
-          - else
-            %span You don`t have one yet. Click generate to fix it.
-            = f.submit 'Generate', class: "btn success btn-build-token"
+      .tab-pane#tab-password
+        %fieldset.update-password
+          %legend Password
+          = form_for @user, url: update_password_profile_path, method: :put do |f|
+            %div
+              %p.slead After a successful password update you will be redirected to login page where you should login with your new password
+              -if @user.errors.any?
+                .alert.alert-error
+                  %ul
+                    - @user.errors.full_messages.each do |msg|
+                      %li= msg
+              .control-group
+                = f.label :password
+                .controls= f.password_field :password, required: true
+              .control-group
+                = f.label :password_confirmation
+                .controls
+                  = f.password_field :password_confirmation, required: true
+              .control-group
+                .controls
+                  = f.submit 'Save password', class: "btn btn-save"
 
+      - if show_profile_social_tab?
+        .tab-pane#tab-social
+          %fieldset
+            %legend Social Accounts
+            .oauth_select_holder
+              %p.hint Tip: Click on icon to activate signin with one of the following services
+              - enabled_social_providers.each do |provider|
+                %span{class: oauth_active_class(provider) }
+                  = link_to authbutton(provider, 32), omniauth_authorize_path(User, provider)
 
-- if current_user.can_change_username?
-  %fieldset.update-username
-    %legend
-      Username
-      %small.cred.pull-right
-        Changing your username can have unintended side effects!
-    = form_for @user, url: update_username_profile_path,  method: :put, remote: true do |f|
-      .padded
-        = f.label :username
-        .controls
-          = f.text_field :username, required: true
-          &nbsp;
-          %span.loading-gif.hide= image_tag "ajax_loader.gif"
-          %span.update-success.cgreen.hide
-            %i.icon-ok
-            Saved
-          %span.update-failed.cred.hide
-            %i.icon-remove
-            Failed
-          %ul.cred
-            %li This will change the web URL for personal projects.
-            %li This will change the git path to repositories for personal projects.
-        .controls
-          = f.submit 'Save username', class: "btn btn-save"
+      - if show_profile_username_tab?
+        .tab-pane#tab-username
+          %fieldset.update-username
+            %legend
+              Username
+              %small.cred.pull-right
+                Changing your username can have unintended side effects!
+            = form_for @user, url: update_username_profile_path,  method: :put, remote: true do |f|
+              %div
+              .control-group
+                = f.label :username
+                .controls
+                  = f.text_field :username, required: true
+                  &nbsp;
+                  %span.loading-gif.hide= image_tag "ajax_loader.gif"
+                  %span.update-success.cgreen.hide
+                    %i.icon-ok
+                    Saved
+                  %span.update-failed.cred.hide
+                    %i.icon-remove
+                    Failed
+                  %ul.cred
+                    %li This will change the web URL for personal projects.
+                    %li This will change the git path to repositories for personal projects.
+                .controls
+                  = f.submit 'Save username', class: "btn btn-save"
 
-- if gitlab_config.signup_enabled && !current_user.ldap_user?
-  %fieldset.remove-account
-    %legend
-      Remove account
-      %small.cred.pull-right
-        Before removing the account you must remove all projects!
-    = link_to 'Delete account', user_registration_path, confirm: "REMOVE #{current_user.name}? Are you sure?", method: :delete, class: "btn btn-remove delete-key btn-small pull-right"
+      - if show_profile_remove_tab?
+        .tab-pane#tab-remove
+          %fieldset.remove-account
+            %legend
+              Remove account
+            %div
+              %p Deleting an account has the following effects:
+              %ul
+                %li All user content like authored issues, snippets, comments will be removed
+                - rp = current_user.personal_projects.count
+                - unless rp.zero?
+                  %li #{pluralize rp, 'personal project'} will be removed and cannot be restored
+                - if current_user.solo_owned_groups.present?
+                  %li
+                    Next groups will be abandoned. You should transfer or remove them:
+                    %strong #{current_user.solo_owned_groups.map(&:name).join(', ')}
+              = link_to 'Delete account', user_registration_path, confirm: "REMOVE #{current_user.name}? Are you sure?", method: :delete, class: "btn btn-remove"
-- 
GitLab


From 5a2c1625d2b2d96c09d1f1c94b71bbe8598fc431 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 4 Sep 2013 00:53:13 +0300
Subject: [PATCH 034/248] Rewrite OAuth specs

---
 spec/lib/auth_spec.rb  | 100 +++++------------------------------------
 spec/lib/oauth_spec.rb |  44 ++++++++++++++++++
 2 files changed, 56 insertions(+), 88 deletions(-)
 create mode 100644 spec/lib/oauth_spec.rb

diff --git a/spec/lib/auth_spec.rb b/spec/lib/auth_spec.rb
index 2784d4e2fbe..e05fde95731 100644
--- a/spec/lib/auth_spec.rb
+++ b/spec/lib/auth_spec.rb
@@ -3,102 +3,26 @@ require 'spec_helper'
 describe Gitlab::Auth do
   let(:gl_auth) { Gitlab::Auth.new }
 
-  before do
-    Gitlab.config.stub(omniauth: {})
-
-    @info = mock(
-      uid: '12djsak321',
-      name: 'John',
-      email: 'john@mail.com'
-    )
-  end
-
-  describe :find_for_ldap_auth do
+  describe :find do
     before do
-      @auth = mock(
-        uid: '12djsak321',
-        info: @info,
-        provider: 'ldap'
+      @user = create(
+        :user,
+        username: 'john',
+        password: '888777',
+        password_confirmation: '888777'
       )
     end
 
-    it "should find by uid & provider" do
-      User.should_receive :find_by_extern_uid_and_provider
-      gl_auth.find_for_ldap_auth(@auth)
-    end
-
-    it "should update credentials by email if missing uid" do
-      user = double('User')
-      User.stub find_by_extern_uid_and_provider: nil
-      User.stub find_by_email: user
-      user.should_receive :update_attributes
-      gl_auth.find_for_ldap_auth(@auth)
-    end
-
-
-    it "should create from auth if user does not exist"do
-      User.stub find_by_extern_uid_and_provider: nil
-      User.stub find_by_email: nil
-      gl_auth.should_receive :create_from_omniauth
-      gl_auth.find_for_ldap_auth(@auth)
-    end
-  end
-
-  describe :find_or_new_for_omniauth do
-    before do
-      @auth = mock(
-        info: @info,
-        provider: 'twitter',
-        uid: '12djsak321',
-      )
+    it "should find user by valid login/password" do
+      gl_auth.find('john', '888777').should == @user
     end
 
-    it "should find user"do
-      User.should_receive :find_by_provider_and_extern_uid
-      gl_auth.should_not_receive :create_from_omniauth
-      gl_auth.find_or_new_for_omniauth(@auth)
+    it "should not find user with invalid password" do
+      gl_auth.find('john', 'invalid').should_not == @user
     end
 
-    it "should not create user"do
-      User.stub find_by_provider_and_extern_uid: nil
-      gl_auth.should_not_receive :create_from_omniauth
-      gl_auth.find_or_new_for_omniauth(@auth)
-    end
-
-    it "should create user if single_sing_on"do
-      Gitlab.config.omniauth['allow_single_sign_on'] = true
-      User.stub find_by_provider_and_extern_uid: nil
-      gl_auth.should_receive :create_from_omniauth
-      gl_auth.find_or_new_for_omniauth(@auth)
-    end
-  end
-
-  describe :create_from_omniauth do
-    it "should create user from LDAP" do
-      @auth = mock(info: @info, provider: 'ldap')
-      user = gl_auth.create_from_omniauth(@auth, true)
-
-      user.should be_valid
-      user.extern_uid.should == @info.uid
-      user.provider.should == 'ldap'
-    end
-
-    it "should create user from Omniauth" do
-      @auth = mock(info: @info, provider: 'twitter')
-      user = gl_auth.create_from_omniauth(@auth, false)
-
-      user.should be_valid
-      user.extern_uid.should == @info.uid
-      user.provider.should == 'twitter'
-    end
-
-    it "should apply defaults to user" do
-      @auth = mock(info: @info, provider: 'ldap')
-      user = gl_auth.create_from_omniauth(@auth, true)
-
-      user.should be_valid
-      user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit
-      user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group
+    it "should not find user with invalid login and password" do
+      gl_auth.find('jon', 'invalid').should_not == @user
     end
   end
 end
diff --git a/spec/lib/oauth_spec.rb b/spec/lib/oauth_spec.rb
new file mode 100644
index 00000000000..e21074554b6
--- /dev/null
+++ b/spec/lib/oauth_spec.rb
@@ -0,0 +1,44 @@
+require 'spec_helper'
+
+describe Gitlab::OAuth::User do
+  let(:gl_auth) { Gitlab::OAuth::User }
+
+  before do
+    Gitlab.config.stub(omniauth: {})
+
+    @info = mock(
+      uid: '12djsak321',
+      name: 'John',
+      email: 'john@mail.com'
+    )
+  end
+
+  describe :create do
+    it "should create user from LDAP" do
+      @auth = mock(info: @info, provider: 'ldap')
+      user = gl_auth.create(@auth)
+
+      user.should be_valid
+      user.extern_uid.should == @info.uid
+      user.provider.should == 'ldap'
+    end
+
+    it "should create user from Omniauth" do
+      @auth = mock(info: @info, provider: 'twitter')
+      user = gl_auth.create(@auth)
+
+      user.should be_valid
+      user.extern_uid.should == @info.uid
+      user.provider.should == 'twitter'
+    end
+
+    it "should apply defaults to user" do
+      @auth = mock(info: @info, provider: 'ldap')
+      user = gl_auth.create(@auth)
+
+      user.should be_valid
+      user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit
+      user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group
+    end
+  end
+end
-- 
GitLab


From 8714080851a6da1ec61c306fc89f9fa539d5f828 Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Wed, 4 Sep 2013 09:08:39 +0200
Subject: [PATCH 035/248] spelling mistake.

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

diff --git a/PROCESS.md b/PROCESS.md
index a7a61c5231a..668cacc870a 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -26,7 +26,7 @@ Below we describe the contributing process to GitLab for two reasons. So that co
 - Close fixed issues (via commit messages or manually)
 - Codes [new features](http://feedback.gitlab.com/forums/176466-general/filters/top)!
 - Response guidelines
-- Be kind to people trying to contribute. Be aware that people can be a non-native or a native English speaker, they might not understand thing or they might be very sensitive to how your word things. Use emoji to express your feelings (hearth, star, smile, etc.). Some good tips about giving feedback to pull requests is in the [Thoughtbot code review guide](https://github.com/thoughtbot/guides/tree/master/code-review).
+- Be kind to people trying to contribute. Be aware that people can be a non-native or a native English speaker, they might not understand thing or they might be very sensitive to how your word things. Use emoji to express your feelings (heart, star, smile, etc.). Some good tips about giving feedback to pull requests is in the [Thoughtbot code review guide](https://github.com/thoughtbot/guides/tree/master/code-review).
 
 ## Priorities of the issue team
 
-- 
GitLab


From 17f75e79d2069ca3dc3c0e2cc9dde3475e1c020c Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 4 Sep 2013 16:20:40 +0300
Subject: [PATCH 036/248] Fix user remove tests. Remove user even if he has
 projects

---
 app/controllers/registrations_controller.rb |  3 ---
 spec/features/profile_spec.rb               | 16 +---------------
 2 files changed, 1 insertion(+), 18 deletions(-)

diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 194dfcd4122..5f18bac82ed 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -2,9 +2,6 @@ class RegistrationsController < Devise::RegistrationsController
   before_filter :signup_enabled?
 
   def destroy
-    if current_user.owned_projects.count > 0
-      redirect_to account_profile_path, alert: "Remove projects and groups before removing account." and return
-    end
     current_user.destroy
 
     respond_to do |format|
diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb
index 7fa474d0ea1..80c9f5d7f14 100644
--- a/spec/features/profile_spec.rb
+++ b/spec/features/profile_spec.rb
@@ -17,26 +17,12 @@ describe "Profile account page" do
 
     it { page.should have_content("Remove account") }
 
-    it "should delete the account", js: true do
+    it "should delete the account" do
       expect { click_link "Delete account" }.to change {User.count}.by(-1)
       current_path.should == new_user_session_path
     end
   end
 
-  describe "when signup is enabled and user has a project" do
-    before do
-      Gitlab.config.gitlab.stub(:signup_enabled).and_return(true)
-      @project = create(:project, namespace: @user.namespace)
-      @project.team << [@user, :master]
-      visit account_profile_path
-    end
-    it { page.should have_content("Remove account") }
-
-    it "should not allow user to delete the account" do
-      expect { click_link "Delete account" }.not_to change {User.count}.by(-1)
-    end
-  end
-
   describe "when signup is disabled" do
     before do
       Gitlab.config.gitlab.stub(:signup_enabled).and_return(false)
-- 
GitLab


From a1a1b1bb4aa3831fdb5a6e242ea7b655834ea350 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 4 Sep 2013 17:05:48 +0300
Subject: [PATCH 037/248] Respect group members in mentionable concern

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

diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb
index 27e39339ae8..5858fe1bb6f 100644
--- a/app/models/concerns/mentionable.rb
+++ b/app/models/concerns/mentionable.rb
@@ -50,7 +50,7 @@ module Mentionable
     matches.each do |match|
       identifier = match.delete "@"
       if has_project
-        id = project.users_projects.joins(:user).where(users: { username: identifier }).pluck(:user_id).first
+        id = project.team.members.find { |u| u.username == identifier }.try(:id)
       else
         id = User.where(username: identifier).pluck(:id).first
       end
-- 
GitLab


From a04b0517fa6383c8126d340ce16aa9544f3c7bea Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 4 Sep 2013 18:15:42 +0300
Subject: [PATCH 038/248] Improve commit diff

* show highlights when replace empty line with content
* show inline diff when replace line with spaces with content
---
 lib/gitlab/inline_diff.rb | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/lib/gitlab/inline_diff.rb b/lib/gitlab/inline_diff.rb
index 44cf49b4047..89c8e0680c3 100644
--- a/lib/gitlab/inline_diff.rb
+++ b/lib/gitlab/inline_diff.rb
@@ -13,6 +13,9 @@ module Gitlab
           second_line = diff_arr[index+2]
           max_length = [first_line.size, second_line.size].max
 
+          # Skip inline diff if empty line was replaced with content
+          next if first_line == "-\n"
+
           first_the_same_symbols = 0
           (0..max_length + 1).each do |i|
             first_the_same_symbols = i - 1
@@ -20,10 +23,19 @@ module Gitlab
               break
             end
           end
+
           first_token = first_line[0..first_the_same_symbols][1..-1]
           start = first_token + START
-          diff_arr[index+1].sub!(first_token, first_token => start)
-          diff_arr[index+2].sub!(first_token, first_token => start)
+
+          if first_token.empty?
+            # In case if we remove string of spaces in commit
+            diff_arr[index+1].sub!("-", "-" => "-#{START}")
+            diff_arr[index+2].sub!("+", "+" => "+#{START}")
+          else
+            diff_arr[index+1].sub!(first_token, first_token => start)
+            diff_arr[index+2].sub!(first_token, first_token => start)
+          end
+
           last_the_same_symbols = 0
           (1..max_length + 1).each do |i|
             last_the_same_symbols = -i
-- 
GitLab


From 1c4e6709c39db3b60d43d8483f9bf5508aa2aa88 Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Wed, 4 Sep 2013 11:19:03 -0400
Subject: [PATCH 039/248] Add group membership api

Change-Id: I5b174bba02856ede788dcb51ec9b0d598ea7d0df
---
 doc/api/groups.md                |  62 +++++++++++++++++
 lib/api/entities.rb              |   6 ++
 lib/api/groups.rb                |  73 +++++++++++++++++--
 spec/requests/api/groups_spec.rb | 116 ++++++++++++++++++++++++++++---
 4 files changed, 243 insertions(+), 14 deletions(-)

diff --git a/doc/api/groups.md b/doc/api/groups.md
index e9702ea2cd1..9c551fff83a 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -55,3 +55,65 @@ POST  /groups/:id/projects/:project_id
 Parameters:
 + `id` (required) - The ID of a group
 + `project_id (required) - The ID of a project
+
+
+## Group members
+
+### List group members
+
+Get a list of group members viewable by the authenticated user.
+
+```
+GET /groups/:id/members
+```
+
+```json
+[
+  {
+    id: 1,
+    username: "raymond_smith",
+    email: "ray@smith.org",
+    name: "Raymond Smith",
+    state: "active",
+    created_at: "2012-10-22T14:13:35Z",
+    access_level: 30
+  },
+  {
+    id: 2,
+    username: "john_doe",
+    email: "joh@doe.org",
+    name: "John Doe",
+    state: "active",
+    created_at: "2012-10-22T14:13:35Z",
+    access_level: 30
+  }
+]
+```
+
+### Add group member
+
+Adds a user to the list of group members.
+
+```
+POST /groups/:id/members
+```
+
+Parameters:
+
++ `id` (required) - The ID of a group
++ `user_id` (required) - The ID of a user to add
++ `access_level` (required) - Project access level
+
+
+### Remove user team member
+
+Removes user from user team.
+
+```
+DELETE /groups/:id/members/:user_id
+```
+
+Parameters:
+
++ `id` (required) - The ID of a user group
++ `user_id` (required) - The ID of a group member
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index f15ca35e954..1f35e9ec5fc 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -67,6 +67,12 @@ module API
       expose :projects, using: Entities::Project
     end
 
+    class GroupMember < UserBasic
+      expose :group_access, as: :access_level do |user, options|
+        options[:group].users_groups.find_by_user_id(user.id).group_access
+      end
+    end
+
     class RepoObject < Grape::Entity
       expose :name, :commit
       expose :protected do |repo, options|
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 701f6777b77..54393740867 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -4,6 +4,19 @@ module API
     before { authenticate! }
 
     resource :groups do
+      helpers do
+        def find_group(id)
+          group = Group.find(id)
+          if current_user.admin or current_user.groups.include? group
+            group
+          else
+            render_api_error!("403 Forbidden - #{current_user.username} lacks sufficient access to #{group.name}", 403)
+          end
+        end
+        def validate_access_level?(level)
+          [UsersGroup::GUEST, UsersGroup::REPORTER, UsersGroup::DEVELOPER, UsersGroup::MASTER].include? level.to_i
+        end
+      end
       # Get a groups list
       #
       # Example Request:
@@ -46,12 +59,8 @@ module API
       # Example Request:
       #   GET /groups/:id
       get ":id" do
-        @group = Group.find(params[:id])
-        if current_user.admin or current_user.groups.include? @group
-          present @group, with: Entities::GroupDetail
-        else
-          not_found!
-        end
+        group = find_group(params[:id])
+        present group, with: Entities::GroupDetail
       end
 
       # Transfer a project to the Group namespace
@@ -71,6 +80,58 @@ module API
           not_found!
         end
       end
+
+      # Get a list of group members viewable by the authenticated user.
+      #
+      # Example Request:
+      #  GET /groups/:id/members
+      get ":id/members" do
+        group = find_group(params[:id])
+        members = group.users_groups
+        users = (paginate members).collect { | member| member.user}
+        present users, with: Entities::GroupMember, group: group
+      end
+
+      # Add a user to the list of group members
+      #
+      # Parameters:
+      #   id (required) - group id
+      #   user_id (required) - the users id
+      #   access_level (required) - Project access level
+      # Example Request:
+      #  POST /groups/:id/members
+      post ":id/members" do
+        required_attributes! [:user_id, :access_level]
+        if not validate_access_level?(params[:access_level])
+          render_api_error!("Wrong access level", 422)
+        end
+        group = find_group(params[:id])
+        if group.users_groups.find_by_user_id(params[:user_id])
+          render_api_error!("Already exists", 409)
+        end
+        group.add_users([params[:user_id]], params[:access_level])
+        member = group.users_groups.find_by_user_id(params[:user_id])
+        present member.user, with: Entities::GroupMember, group: group
+      end
+
+      # Remove member.
+      #
+      # Parameters:
+      #   id (required) - group id
+      #   user_id (required) - the users id
+      #
+      # Example Request:
+      #   DELETE /groups/:id/members/:user_id
+      delete ":id/members/:user_id" do
+        group = find_group(params[:id])
+        member =  group.users_groups.find_by_user_id(params[:user_id])
+        if member.nil?
+          render_api_error!("404 Not Found - user_id:#{params[:user_id]} not a member of group #{group.name}",404)
+        else
+          member.destroy
+        end
+      end
+
     end
   end
 end
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index d2e25fb9e23..51d6384a261 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -3,11 +3,11 @@ require 'spec_helper'
 describe API::API do
   include ApiHelpers
 
-  let(:user1)  { create(:user) }
-  let(:user2)  { create(:user) }
+  let(:user1) { create(:user) }
+  let(:user2) { create(:user) }
   let(:admin) { create(:admin) }
-  let!(:group1)  { create(:group, owner: user1) }
-  let!(:group2)  { create(:group, owner: user2) }
+  let!(:group1) { create(:group, owner: user1) }
+  let!(:group2) { create(:group, owner: user2) }
 
   describe "GET /groups" do
     context "when unauthenticated" do
@@ -52,7 +52,7 @@ describe API::API do
 
       it "should not return a group not attached to user1" do
         get api("/groups/#{group2.id}", user1)
-        response.status.should == 404
+        response.status.should == 403
       end
     end
 
@@ -90,7 +90,7 @@ describe API::API do
       end
 
       it "should return 400 bad request error if name not given" do
-        post api("/groups", admin), { path: group2.path }
+        post api("/groups", admin), {path: group2.path}
         response.status.should == 400
       end
 
@@ -104,8 +104,8 @@ describe API::API do
   describe "POST /groups/:id/projects/:project_id" do
     let(:project) { create(:project) }
     before(:each) do
-       project.stub!(:transfer).and_return(true)
-       Project.stub(:find).and_return(project)
+      project.stub!(:transfer).and_return(true)
+      Project.stub(:find).and_return(project)
     end
 
 
@@ -123,4 +123,104 @@ describe API::API do
       end
     end
   end
+
+  describe "members" do
+    let(:owner) { create(:user) }
+    let(:reporter) { create(:user) }
+    let(:developer) { create(:user) }
+    let(:master) { create(:user) }
+    let(:guest) { create(:user) }
+    let!(:group_with_members) do
+      group = create(:group, owner: owner)
+      group.add_users([reporter.id], UsersGroup::REPORTER)
+      group.add_users([developer.id], UsersGroup::DEVELOPER)
+      group.add_users([master.id], UsersGroup::MASTER)
+      group.add_users([guest.id], UsersGroup::GUEST)
+      group
+    end
+    let!(:group_no_members) { create(:group, owner: owner) }
+    describe "GET /groups/:id/members" do
+      context "when authenticated as user that is part or the group" do
+        it "each user: should return an array of members groups of group3" do
+          [owner, master, developer, reporter, guest].each do |user|
+            get api("/groups/#{group_with_members.id}/members", user)
+            response.status.should == 200
+            json_response.should be_an Array
+            json_response.size.should == 5
+            json_response.find { |e| e['id']==owner.id }['access_level'].should == UsersGroup::OWNER
+            json_response.find { |e| e['id']==reporter.id }['access_level'].should == UsersGroup::REPORTER
+            json_response.find { |e| e['id']==developer.id }['access_level'].should == UsersGroup::DEVELOPER
+            json_response.find { |e| e['id']==master.id }['access_level'].should == UsersGroup::MASTER
+            json_response.find { |e| e['id']==guest.id }['access_level'].should == UsersGroup::GUEST
+          end
+        end
+        it "users not part of the group should get access error" do
+          get api("/groups/#{group_with_members.id}/members", user1)
+          response.status.should == 403
+        end
+      end
+    end
+
+    describe "POST /groups/:id/members" do
+      context "when not a member of the group" do
+        it "should not add guest as member of group_no_members when adding being done by person outside the group" do
+          post api("/groups/#{group_no_members.id}/members", reporter), user_id: guest.id, access_level: UsersGroup::MASTER
+          response.status.should == 403
+        end
+      end
+
+      context "when a member of the group" do
+        it "should return ok and add new member" do
+          count_before=group_no_members.users_groups.count
+          new_user = create(:user)
+          post api("/groups/#{group_no_members.id}/members", owner), user_id: new_user.id, access_level: UsersGroup::MASTER
+          response.status.should == 201
+          json_response['name'].should == new_user.name
+          json_response['access_level'].should == UsersGroup::MASTER
+          group_no_members.users_groups.count.should == count_before + 1
+        end
+        it "should return error if member already exists" do
+          post api("/groups/#{group_with_members.id}/members", owner), user_id: master.id, access_level: UsersGroup::MASTER
+          response.status.should == 409
+        end
+        it "should return a 400 error when user id is not given" do
+          post api("/groups/#{group_no_members.id}/members", owner), access_level: UsersGroup::MASTER
+          response.status.should == 400
+        end
+        it "should return a 400 error when access level is not given" do
+          post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id
+          response.status.should == 400
+        end
+
+        it "should return a 422 error when access level is not known" do
+          post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id, access_level: 1234
+          response.status.should == 422
+        end
+
+      end
+    end
+
+    describe "DELETE /groups/:id/members/:user_id" do
+      context "when not a member of the group" do
+        it "should not delete guest's membership of group_with_members" do
+          random_user = create(:user)
+          delete api("/groups/#{group_with_members.id}/members/#{owner.id}", random_user)
+          response.status.should == 403
+        end
+      end
+
+      context "when a member of the group" do
+        it "should delete guest's membership of group" do
+          count_before=group_with_members.users_groups.count
+          delete api("/groups/#{group_with_members.id}/members/#{guest.id}", owner)
+          response.status.should == 200
+          group_with_members.users_groups.count.should == count_before - 1
+        end
+        it "should return a 404 error when user id is not known" do
+          delete api("/groups/#{group_with_members.id}/members/1328", owner)
+          response.status.should == 404
+        end
+      end
+    end
+  end
 end
-- 
GitLab


From b4805b2a203cdcbae56aec0b1eeb6a671eb60c8c Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Thu, 5 Sep 2013 10:17:40 -0400
Subject: [PATCH 040/248] Fixes for @randx

Change-Id: I3b15ae34c0957a0f4026e1886c92a9770e9d170e
---
 lib/api/groups.rb                | 7 ++++---
 spec/requests/api/groups_spec.rb | 8 ++++++--
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 54393740867..396554404af 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -14,9 +14,10 @@ module API
           end
         end
         def validate_access_level?(level)
-          [UsersGroup::GUEST, UsersGroup::REPORTER, UsersGroup::DEVELOPER, UsersGroup::MASTER].include? level.to_i
+          Gitlab::Access.options_with_owner.values.include? level.to_i
         end
       end
+
       # Get a groups list
       #
       # Example Request:
@@ -88,7 +89,7 @@ module API
       get ":id/members" do
         group = find_group(params[:id])
         members = group.users_groups
-        users = (paginate members).collect { | member| member.user}
+        users = (paginate members).collect(&:user)
         present users, with: Entities::GroupMember, group: group
       end
 
@@ -102,7 +103,7 @@ module API
       #  POST /groups/:id/members
       post ":id/members" do
         required_attributes! [:user_id, :access_level]
-        if not validate_access_level?(params[:access_level])
+        unless validate_access_level?(params[:access_level])
           render_api_error!("Wrong access level", 422)
         end
         group = find_group(params[:id])
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 51d6384a261..f7fd27523b0 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -108,7 +108,6 @@ describe API::API do
       Project.stub(:find).and_return(project)
     end
 
-
     context "when authenticated as user" do
       it "should not transfer project to group" do
         post api("/groups/#{group1.id}/projects/#{project.id}", user2)
@@ -139,6 +138,7 @@ describe API::API do
       group
     end
     let!(:group_no_members) { create(:group, owner: owner) }
+
     describe "GET /groups/:id/members" do
       context "when authenticated as user that is part or the group" do
         it "each user: should return an array of members groups of group3" do
@@ -154,6 +154,7 @@ describe API::API do
             json_response.find { |e| e['id']==guest.id }['access_level'].should == UsersGroup::GUEST
           end
         end
+
         it "users not part of the group should get access error" do
           get api("/groups/#{group_with_members.id}/members", user1)
           response.status.should == 403
@@ -179,14 +180,17 @@ describe API::API do
           json_response['access_level'].should == UsersGroup::MASTER
           group_no_members.users_groups.count.should == count_before + 1
         end
+
         it "should return error if member already exists" do
           post api("/groups/#{group_with_members.id}/members", owner), user_id: master.id, access_level: UsersGroup::MASTER
           response.status.should == 409
         end
+
         it "should return a 400 error when user id is not given" do
           post api("/groups/#{group_no_members.id}/members", owner), access_level: UsersGroup::MASTER
           response.status.should == 400
         end
+
         it "should return a 400 error when access level is not given" do
           post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id
           response.status.should == 400
@@ -196,7 +200,6 @@ describe API::API do
           post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id, access_level: 1234
           response.status.should == 422
         end
-
       end
     end
 
@@ -216,6 +219,7 @@ describe API::API do
           response.status.should == 200
           group_with_members.users_groups.count.should == count_before - 1
         end
+
         it "should return a 404 error when user id is not known" do
           delete api("/groups/#{group_with_members.id}/members/1328", owner)
           response.status.should == 404
-- 
GitLab


From dbb2f893ae89b7a67ab6a727eab8c70fbf697094 Mon Sep 17 00:00:00 2001
From: Jeff '2 bits' Bachtel <jbachtel@bericotechnologies.com>
Date: Fri, 6 Sep 2013 18:53:10 -0400
Subject: [PATCH 041/248] -i flag allows sudo to work for git users using rvm
 that is not being used by root user (su might be better)

---
 lib/support/init.d/gitlab | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
index 79c56a9854b..dbdf7db114b 100755
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -35,7 +35,7 @@ sidekiq_pid_path="$pid_path/sidekiq.pid"
 
 # Switch to the app_user if it is not he/she who is running the script.
 if [ "$USER" != "$app_user" ]; then
-  sudo -u "$app_user" -H $0 "$@"; exit;
+  sudo -u "$app_user" -H -i $0 "$@"; exit;
 fi
 
 # Switch to the gitlab path, if it fails exit with an error.
-- 
GitLab


From 8dda5fd78e9f337bf644c1138e23b37e407f5d1a Mon Sep 17 00:00:00 2001
From: "C. Walker" <clayzermk1@gmail.com>
Date: Fri, 6 Sep 2013 16:18:09 -0700
Subject: [PATCH 042/248] Fixed description.

---
 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 668ef1d2300..f2cba162784 100644
--- a/lib/tasks/gitlab/import.rake
+++ b/lib/tasks/gitlab/import.rake
@@ -9,7 +9,7 @@ namespace :gitlab do
     #  * project owner will be a first admin
     #  * existing projects will be skipped
     #
-    desc "GITLAB | Import bare repositories from git_host -> base_path into GitLab project instance"
+    desc "GITLAB | Import bare repositories from gitlab_shell -> repos_path into GitLab project instance"
     task repos: :environment do
 
       git_base_path = Gitlab.config.gitlab_shell.repos_path
-- 
GitLab


From 70e9bc3379ae0718139c4c8f11ae8663faf77b1c Mon Sep 17 00:00:00 2001
From: "C. Walker" <clayzermk1@gmail.com>
Date: Fri, 6 Sep 2013 16:19:35 -0700
Subject: [PATCH 043/248] Fixed Import Bare Repositories instructions to match
 rake task.

---
 doc/raketasks/maintenance.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md
index 68c1a72b230..3033d8c46b4 100644
--- a/doc/raketasks/maintenance.md
+++ b/doc/raketasks/maintenance.md
@@ -122,7 +122,7 @@ Notes:
 
 How to use:
 
-1. copy your bare repos under git base_path (see `config/gitlab.yml` git_host -> base_path)
+1. copy your bare repos under git repos_path (see `config/gitlab.yml` gitlab_shell -> repos_path)
 2. run the command below
 
 ```
-- 
GitLab


From 7c13d3e6e63312fc5a2e10a168cb568cb152f7b4 Mon Sep 17 00:00:00 2001
From: "C. Walker" <clayzermk1@gmail.com>
Date: Fri, 6 Sep 2013 16:45:42 -0700
Subject: [PATCH 044/248] Forgot to fix the comment instructions.

---
 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 f2cba162784..8fa89270854 100644
--- a/lib/tasks/gitlab/import.rake
+++ b/lib/tasks/gitlab/import.rake
@@ -2,7 +2,7 @@ namespace :gitlab do
   namespace :import do
     # How to use:
     #
-    #  1. copy your bare repos under git base_path
+    #  1. copy your bare repos under git repos_path
     #  2. run bundle exec rake gitlab:import:repos RAILS_ENV=production
     #
     # Notes:
-- 
GitLab


From 60036c868c43eef01319b5f1c1153cb4c6af370a Mon Sep 17 00:00:00 2001
From: Boyan Tabakov <boyan.tabakov@futurice.com>
Date: Wed, 4 Sep 2013 10:33:09 +0300
Subject: [PATCH 045/248] Improved large commit handling.

Previously, only number of changed files mattered. Now, number of lines to render in the diff are also taken into account.

A hard limit is set, above which diffs are not rendered and users are not allowed to override that. This prevents high server
resource usage with huge commits.

Related to #1745, #2259

In addition, handle large commits for MergeRequests and Compare controllers.

Also fixes a bug where diffs are loaded twice, if user goes directly to merge_requests/:id/diffs URL.
---
 .../javascripts/merge_requests.js.coffee      |  2 +-
 app/contexts/commit_load_context.rb           |  3 +-
 app/controllers/projects/commit_controller.rb |  1 +
 .../projects/compare_controller.rb            |  4 ++
 .../projects/merge_requests_controller.rb     |  4 ++
 app/models/commit.rb                          | 43 ++++++++++++++++++-
 app/views/projects/commits/_diffs.html.haml   | 22 ++++++++--
 features/project/commits/commits.feature      |  8 ++++
 .../steps/project/project_browse_commits.rb   | 20 +++++++++
 features/support/env.rb                       |  2 +-
 spec/support/big_commits.rb                   |  8 ++++
 11 files changed, 108 insertions(+), 9 deletions(-)
 create mode 100644 spec/support/big_commits.rb

diff --git a/app/assets/javascripts/merge_requests.js.coffee b/app/assets/javascripts/merge_requests.js.coffee
index 153198ca5c5..5400bc5c1ad 100644
--- a/app/assets/javascripts/merge_requests.js.coffee
+++ b/app/assets/javascripts/merge_requests.js.coffee
@@ -11,7 +11,7 @@ class MergeRequest
 
   constructor: (@opts) ->
     this.$el = $('.merge-request')
-    @diffs_loaded = false
+    @diffs_loaded = if @opts.action == 'diffs' then true else false
     @commits_loaded = false
 
     this.activateTab(@opts.action)
diff --git a/app/contexts/commit_load_context.rb b/app/contexts/commit_load_context.rb
index 2cf5420d62d..2930c5b1668 100644
--- a/app/contexts/commit_load_context.rb
+++ b/app/contexts/commit_load_context.rb
@@ -20,7 +20,8 @@ class CommitLoadContext < BaseContext
       result[:notes_count] = project.notes.for_commit_id(commit.id).count
 
       begin
-        result[:suppress_diff] = true if commit.diffs.size > Commit::DIFF_SAFE_SIZE && !params[:force_show_diff]
+        result[:suppress_diff] = true if commit.diff_suppress? && !params[:force_show_diff]
+        result[:force_suppress_diff] = commit.diff_force_suppress?
       rescue Grit::Git::GitTimeout
         result[:suppress_diff] = true
         result[:status] = :huge_commit
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index 6a2d2315c1d..bdc501d73bb 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -18,6 +18,7 @@ class Projects::CommitController < Projects::ApplicationController
     end
 
     @suppress_diff = result[:suppress_diff]
+    @force_suppress_diff = result[:force_suppress_diff]
 
     @note        = result[:note]
     @line_notes  = result[:line_notes]
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index 126a2ea50c9..d7e660dac22 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -15,6 +15,10 @@ class Projects::CompareController < Projects::ApplicationController
     @diffs         = compare.diffs
     @refs_are_same = compare.same
     @line_notes    = []
+
+    diff_line_count = Commit::diff_line_count(@diffs)
+    @suppress_diff = Commit::diff_suppress?(@diffs, diff_line_count) && !params[:force_show_diff]
+    @force_suppress_diff = Commit::diff_force_suppress?(@diffs, diff_line_count)
   end
 
   def create
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 55d2c3f04fc..3bc50b0418f 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -40,6 +40,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController
     @comments_target = {noteable_type: 'MergeRequest',
                         noteable_id: @merge_request.id}
     @line_notes = @merge_request.notes.where("line_code is not null")
+
+    diff_line_count = Commit::diff_line_count(@merge_request.diffs)
+    @suppress_diff = Commit::diff_suppress?(@merge_request.diffs, diff_line_count) && !params[:force_show_diff]
+    @force_suppress_diff = Commit::diff_force_suppress?(@merge_request.diffs, diff_line_count)
   end
 
   def new
diff --git a/app/models/commit.rb b/app/models/commit.rb
index f8ca6a5fe82..dd1f9801878 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -6,15 +6,41 @@ class Commit
 
   attr_mentionable :safe_message
 
-  # Safe amount of files with diffs in one commit to render
+  # Safe amount of changes (files and lines) in one commit to render
   # Used to prevent 500 error on huge commits by suppressing diff
   #
-  DIFF_SAFE_SIZE = 100
+  # User can force display of diff above this size
+  DIFF_SAFE_FILES  = 100
+  DIFF_SAFE_LINES  = 5000
+  # Commits above this size will not be rendered in HTML
+  DIFF_HARD_LIMIT_FILES = 500
+  DIFF_HARD_LIMIT_LINES = 10000
 
   def self.decorate(commits)
     commits.map { |c| self.new(c) }
   end
 
+  # Calculate number of lines to render for diffs
+  def self.diff_line_count(diffs)
+    diffs.reduce(0){|sum, d| sum + d.diff.lines.count}
+  end
+
+  def self.diff_suppress?(diffs, line_count = nil)
+    # optimize - check file count first
+    return true if diffs.size > DIFF_SAFE_FILES
+
+    line_count ||= Commit::diff_line_count(diffs)
+    line_count > DIFF_SAFE_LINES
+  end
+
+  def self.diff_force_suppress?(diffs, line_count = nil)
+    # optimize - check file count first
+    return true if diffs.size > DIFF_HARD_LIMIT_FILES
+
+    line_count ||= Commit::diff_line_count(diffs)
+    line_count > DIFF_HARD_LIMIT_LINES
+  end
+
   attr_accessor :raw
 
   def initialize(raw_commit)
@@ -27,6 +53,19 @@ class Commit
     @raw.id
   end
 
+  def diff_line_count
+    @diff_line_count ||= Commit::diff_line_count(self.diffs)
+    @diff_line_count
+  end
+
+  def diff_suppress?
+    Commit::diff_suppress?(self.diffs, diff_line_count)
+  end
+
+  def diff_force_suppress?
+    Commit::diff_force_suppress?(self.diffs, diff_line_count)
+  end
+
   # Returns a string describing the commit for use in a link title
   #
   # Example
diff --git a/app/views/projects/commits/_diffs.html.haml b/app/views/projects/commits/_diffs.html.haml
index 5a3a9bd16af..c51f1b6eff5 100644
--- a/app/views/projects/commits/_diffs.html.haml
+++ b/app/views/projects/commits/_diffs.html.haml
@@ -1,11 +1,25 @@
+- @suppress_diff ||= @suppress_diff || @force_suppress_diff
 - if @suppress_diff
   .alert.alert-block
     %p
-      %strong Warning! Large commit with more than #{Commit::DIFF_SAFE_SIZE} files changed.
-    %p To preserve performance the diff is not shown.
+      %strong Warning! This is a large diff.
     %p
-      But if you still want to see the diff
-      = link_to "click this link", project_commit_path(project, @commit, force_show_diff: true), class: "underlined_link"
+      To preserve performance the diff is not shown.
+      - if current_controller?(:commit) or current_controller?(:merge_requests)
+        Please, download the diff as
+        - if current_controller?(:commit)
+          = link_to "plain diff", project_commit_path(@project, @commit, format: :diff), class: "underlined_link"
+          or
+          = link_to "email patch", project_commit_path(@project, @commit, format: :patch), class: "underlined_link"
+        - else
+          = link_to "plain diff", project_merge_request_path(@project, @merge_request, format: :diff), class: "underlined_link"
+          or
+          = link_to "email patch", project_merge_request_path(@project, @merge_request, format: :patch), class: "underlined_link"
+        instead.
+    - unless @force_suppress_diff
+      %p
+        If you still want to see the diff
+        = link_to "click this link", url_for(force_show_diff: true), class: "underlined_link"
 
 %p.commit-stat-summary
   Showing
diff --git a/features/project/commits/commits.feature b/features/project/commits/commits.feature
index 56069cdc977..d962471ebdb 100644
--- a/features/project/commits/commits.feature
+++ b/features/project/commits/commits.feature
@@ -27,3 +27,11 @@ Feature: Project Browse commits
   Scenario: I browse commits stats
     Given I visit my project's commits stats page
     Then I see commits stats
+
+  Scenario: I browse big commit
+    Given I visit big commit page
+    Then I see big commit warning
+
+  Scenario: I browse huge commit
+    Given I visit huge commit page
+    Then I see huge commit message
diff --git a/features/steps/project/project_browse_commits.rb b/features/steps/project/project_browse_commits.rb
index 71f4bd79f7e..4b122b853e6 100644
--- a/features/steps/project/project_browse_commits.rb
+++ b/features/steps/project/project_browse_commits.rb
@@ -58,4 +58,24 @@ class ProjectBrowseCommits < Spinach::FeatureSteps
     page.should have_content 'Total commits'
     page.should have_content 'Authors'
   end
+
+  Given 'I visit big commit page' do
+    visit project_commit_path(@project, BigCommits::BIG_COMMIT_ID)
+  end
+
+  Then 'I see big commit warning' do
+    page.should have_content BigCommits::BIG_COMMIT_MESSAGE
+    page.should have_content "Warning! This is a large diff"
+    page.should have_content "If you still want to see the diff"
+  end
+
+  Given 'I visit huge commit page' do
+    visit project_commit_path(@project, BigCommits::HUGE_COMMIT_ID)
+  end
+
+  Then 'I see huge commit message' do
+    page.should have_content BigCommits::HUGE_COMMIT_MESSAGE
+    page.should have_content "Warning! This is a large diff"
+    page.should_not have_content "If you still want to see the diff"
+  end
 end
diff --git a/features/support/env.rb b/features/support/env.rb
index 0cc7d8d2fe9..61f8dc29670 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -14,7 +14,7 @@ require 'spinach/capybara'
 require 'sidekiq/testing/inline'
 
 
-%w(valid_commit select2_helper chosen_helper test_env).each do |f|
+%w(valid_commit big_commits select2_helper chosen_helper test_env).each do |f|
   require Rails.root.join('spec', 'support', f)
 end
 
diff --git a/spec/support/big_commits.rb b/spec/support/big_commits.rb
new file mode 100644
index 00000000000..69daa709dd9
--- /dev/null
+++ b/spec/support/big_commits.rb
@@ -0,0 +1,8 @@
+module BigCommits
+  HUGE_COMMIT_ID = "7f92534f767fa20357a11c63f973ae3b79cc5b85"
+  HUGE_COMMIT_MESSAGE = "pybments.rb version up. gitignore improved"
+
+  BIG_COMMIT_ID = "d62200cad430565bd9f80befaf329297120330b5"
+  BIG_COMMIT_MESSAGE = "clean-up code"
+end
+
-- 
GitLab


From 9525c455011333adf67f88ec6f2cbe99f1adda0c Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Sun, 8 Sep 2013 12:31:00 +0200
Subject: [PATCH 046/248] Consistent status.

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

diff --git a/README.md b/README.md
index 19e7cbaad68..a4c5c0d0534 100644
--- a/README.md
+++ b/README.md
@@ -80,7 +80,7 @@ Since 2011 GitLab is released on the 22nd of every month. Every new release incl
 
 * [Changelog](CHANGELOG)
 
-* Features that will be in the next releases are listed on [the feedback and suggestions forum](http://feedback.gitlab.com/forums/176466-general) with the status ["started"](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457).
+* Features that will be in the next releases are listed on [the feedback and suggestions forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457).
 
 
 ### Run in production mode
-- 
GitLab


From 7e783906c360f504fdf596eb0bf0a2e859a42020 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 9 Sep 2013 16:20:43 +0300
Subject: [PATCH 047/248] Move commits dates to left

---
 app/assets/stylesheets/sections/commits.scss  | 15 +++++++++++++++
 app/views/projects/commits/_commits.html.haml | 16 +++++++++-------
 2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
index faae0e127d9..2f4472a52e1 100644
--- a/app/assets/stylesheets/sections/commits.scss
+++ b/app/assets/stylesheets/sections/commits.scss
@@ -374,6 +374,15 @@
     min-width: 65px;
     font-family: $monospace_font;
   }
+
+  .row_title {
+    font-weight: bold;
+    color: #444;
+    &:hover {
+      color: #444;
+      text-decoration: underline;
+    }
+  }
 }
 
 .file-stats a {
@@ -496,3 +505,9 @@ li.commit {
     font-weight: bold;
   }
 }
+
+.commits-row {
+  padding-bottom: 10px;
+  margin-bottom: 10px;
+  border-bottom: 1px solid #DDD;
+}
diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml
index fd0616f9acc..b6eeeb92287 100644
--- a/app/views/projects/commits/_commits.html.haml
+++ b/app/views/projects/commits/_commits.html.haml
@@ -1,8 +1,10 @@
 - @commits.group_by { |c| c.committed_date.to_date }.sort.reverse.each do |day, commits|
-  .ui-box.small-box
-    .title
-      %i.icon-calendar
-      %span= day.stamp("28 Aug, 2010")
-      .pull-right
-        %small= pluralize(commits.count, 'commit')
-    %ul.well-list= render commits, project: @project
+  .row.commits-row
+    .span2
+      %h4
+        %i.icon-calendar
+        %span= day.stamp("28 Aug, 2010")
+      %p= pluralize(commits.count, 'commit')
+    .span10
+      %ul.well-list
+        = render commits, project: @project
-- 
GitLab


From 7a7494d3122b99b43801abdf788d4486a4924ca1 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 9 Sep 2013 16:32:43 +0300
Subject: [PATCH 048/248] Add description to MergeRequest model

---
 app/models/concerns/issuable.rb                              | 2 ++
 app/models/issue.rb                                          | 1 -
 app/models/merge_request.rb                                  | 3 +--
 .../20130909132950_add_description_to_merge_request.rb       | 5 +++++
 db/schema.rb                                                 | 3 ++-
 5 files changed, 10 insertions(+), 4 deletions(-)
 create mode 100644 db/migrate/20130909132950_add_description_to_merge_request.rb

diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index a05dba7f6b6..7f820f950b0 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -37,6 +37,8 @@ module Issuable
              prefix: true
 
     attr_accessor :author_id_of_changes
+
+    attr_mentionable :title, :description
   end
 
   module ClassMethods
diff --git a/app/models/issue.rb b/app/models/issue.rb
index ffe9681fc83..f3ec322126f 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -32,7 +32,6 @@ class Issue < ActiveRecord::Base
   attr_accessible :title, :assignee_id, :position, :description,
                   :milestone_id, :label_list, :author_id_of_changes,
                   :state_event
-  attr_mentionable :title, :description
 
   acts_as_taggable_on :labels
 
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 514fc79f7c5..7f367588b23 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -30,8 +30,7 @@ class MergeRequest < ActiveRecord::Base
   belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project"
   belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project"
 
-  attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :author_id_of_changes, :state_event
-  attr_mentionable :title
+  attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :author_id_of_changes, :state_event, :description
 
   attr_accessor :should_remove_source_branch
 
diff --git a/db/migrate/20130909132950_add_description_to_merge_request.rb b/db/migrate/20130909132950_add_description_to_merge_request.rb
new file mode 100644
index 00000000000..9bcd0c7ee06
--- /dev/null
+++ b/db/migrate/20130909132950_add_description_to_merge_request.rb
@@ -0,0 +1,5 @@
+class AddDescriptionToMergeRequest < ActiveRecord::Migration
+  def change
+    add_column :merge_requests, :description, :text, null: true
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 654f2b1e8f7..d5effe40ea1 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended to check this file into your version control system.
 
-ActiveRecord::Schema.define(:version => 20130821090531) do
+ActiveRecord::Schema.define(:version => 20130909132950) do
 
   create_table "deploy_keys_projects", :force => true do |t|
     t.integer  "deploy_key_id", :null => false
@@ -100,6 +100,7 @@ ActiveRecord::Schema.define(:version => 20130821090531) do
     t.string   "merge_status"
     t.integer  "target_project_id",                       :null => false
     t.integer  "iid"
+    t.text     "description"
   end
 
   add_index "merge_requests", ["assignee_id"], :name => "index_merge_requests_on_assignee_id"
-- 
GitLab


From 5355ced8db2de41e31c99d33b70b322f7e6ea959 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 9 Sep 2013 17:11:58 +0300
Subject: [PATCH 049/248] Improve Merge Request form

* added description
* simplified form
* enabled gfm autocomplete
---
 app/assets/javascripts/dispatcher.js.coffee   |  2 +
 .../stylesheets/sections/merge_requests.scss  |  2 +-
 .../projects/merge_requests/_form.html.haml   | 57 +++++++++----------
 .../merge_requests/show/_mr_box.html.haml     |  6 ++
 4 files changed, 36 insertions(+), 31 deletions(-)

diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee
index c8ddbed5097..e264e281309 100644
--- a/app/assets/javascripts/dispatcher.js.coffee
+++ b/app/assets/javascripts/dispatcher.js.coffee
@@ -18,6 +18,8 @@ class Dispatcher
     switch page
       when 'projects:issues:index'
         Issues.init()
+      when 'projects:issues:new', 'projects:merge_requests:new'
+        GitLab.GfmAutoComplete.setup()
       when 'dashboard:show'
         new Dashboard()
         new Activities()
diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss
index bdab306a57d..e7b464fd4aa 100644
--- a/app/assets/stylesheets/sections/merge_requests.scss
+++ b/app/assets/stylesheets/sections/merge_requests.scss
@@ -117,7 +117,7 @@
 
 .merge-request-angle {
   text-align: center;
-  margin-top: 45px;
+  margin: 0;
 }
 
 .merge-request-form-info {
diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml
index 5e94f1fdf18..ce72756303e 100644
--- a/app/views/projects/merge_requests/_form.html.haml
+++ b/app/views/projects/merge_requests/_form.html.haml
@@ -5,41 +5,32 @@
         - @merge_request.errors.full_messages.each do |msg|
           %li= msg
 
-  %h3.page-title
-    Branches
   .merge-request-branches
-  .row
-    .span5
-      .ui-box
-        .title From
-        .ui-box-head
-          Project:
-          = f.select(:source_project_id,[[@merge_request.source_project.path_with_namespace,@merge_request.source_project.id]] , {}, {class: 'source_project chosen span4'})
-          .prepend-top-10
+    .row
+      .span5
+        .clearfix
+          .pull-left
+            = f.select(:source_project_id,[[@merge_request.source_project.path_with_namespace,@merge_request.source_project.id]] , {}, {class: 'source_project chosen span3'})
+          .pull-left
+            &nbsp;
             %i.icon-code-fork
-            Branch:
-            = f.select(:source_branch, @merge_request.source_project.repository.branch_names, { include_blank: "Select branch" }, {class: 'source_branch chosen span3'})
-          .mr_source_commit.prepend-top-10
-    .span2
-      %h1.merge-request-angle
-        %i.icon-angle-right
-    .span5
-      .ui-box
-        .title To
-        .ui-box-head
-          - projects =  @project.forked_from_project.nil? ? [@project] : [ @project,@project.forked_from_project]
-          Project:
-          = f.select(:target_project_id, projects.map { |proj| [proj.path_with_namespace,proj.id] }, {include_blank: "Select Target Project" }, {class: 'target_project chosen span4'})
-          .prepend-top-10
+            = f.select(:source_branch, @merge_request.source_project.repository.branch_names, { include_blank: "Select branch" }, {class: 'source_branch chosen span2'})
+        .mr_source_commit.prepend-top-10
+      .span2
+        %h2.merge-request-angle.light
+          %i.icon-long-arrow-right
+      .span5
+        .clearfix
+          .pull-left
+            - projects =  @project.forked_from_project.nil? ? [@project] : [ @project,@project.forked_from_project]
+            = f.select(:target_project_id, projects.map { |proj| [proj.path_with_namespace,proj.id] }, {include_blank: "Select Target Project" }, {class: 'target_project chosen span3'})
+          .pull-left
+            &nbsp;
             %i.icon-code-fork
-            Branch:
-            = f.select(:target_branch, @target_branches, { include_blank: "Select branch" }, {class: 'target_branch chosen span3'})
-          .mr_target_commit.prepend-top-10
+            = f.select(:target_branch, @target_branches, { include_blank: "Select branch" }, {class: 'target_branch chosen span2'})
+        .mr_target_commit.prepend-top-10
 
   %hr
-
-  %h3.page-title
-    Details
   .merge-request-form-info
     .control-group
       = f.label :title do
@@ -56,6 +47,12 @@
           %i.icon-time
           Milestone
         .controls= f.select(:milestone_id, @project.milestones.active.all.map {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'})
+    .control-group
+      = f.label :description, "Description"
+      .controls
+        = f.text_area :description, class: "input-xxlarge js-gfm-input", rows: 14
+        %p.hint Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+
 
   .form-actions
     - if @merge_request.new_record?
diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml
index c4b614b51da..1f750e22c65 100644
--- a/app/views/projects/merge_requests/show/_mr_box.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_box.html.haml
@@ -21,6 +21,12 @@
         %strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone)
 
 
+  - if @merge_request.description.present?
+    .ui-box-bottom
+      .wiki
+        = preserve do
+          = markdown @merge_request.description
+
   - if @merge_request.closed?
     .ui-box-bottom.alert-error
       %span
-- 
GitLab


From 020db1974cd962648ad0b7ed13bcbda478214e3e Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ihalpert@blackberry.com>
Date: Thu, 28 Mar 2013 14:37:44 -0400
Subject: [PATCH 050/248] API: admin users can sudo commands as other users

-Specifying a header of SUDO or adding a :sudo with either user id, or username of the user will set the current_user to be that user if your identifying private_token/PRIVATE_TOKEN is an administrator token
---
 doc/api/README.md                     |  36 ++++++
 lib/api/helpers.rb                    |  44 ++++++-
 spec/requests/api/api_helpers_spec.rb | 159 ++++++++++++++++++++++++++
 3 files changed, 234 insertions(+), 5 deletions(-)
 create mode 100644 spec/requests/api/api_helpers_spec.rb

diff --git a/doc/api/README.md b/doc/api/README.md
index 7668df07af1..6971e08f010 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -58,7 +58,43 @@ Return values:
 * `409 Conflict` - A conflicting resource already exists, e.g. creating a project with a name that already exists
 * `500 Server Error` - While handling the request something went wrong on the server side
 
+## Sudo
+All API requests support performing an api call as if you were another user, if your private token is for an administration account. You need to pass  `sudo` parameter by url or header with an id or username of the user you want to perform the operation as. If passed as header, the header name must be "SUDO" (capitals).
 
+If a non administrative `private_token` is provided then an error message will be returned with status code 403:
+
+```json
+{
+  "message": "403 Forbidden: Must be admin to use sudo"
+}
+```
+
+If the sudo user id or username cannot be found then an error message will be returned with status code 404:
+
+```json
+{
+  "message": "404 Not Found: No user id or username for: <id/username>"
+}
+```
+
+Example of a valid API with sudo request:
+
+```
+GET http://example.com/api/v3/projects?private_token=QVy1PB7sTxfy4pqfZM1U&sudo=username
+```
+```
+GET http://example.com/api/v3/projects?private_token=QVy1PB7sTxfy4pqfZM1U&sudo=23
+```
+
+
+Example for a valid API request with sudo using curl and authentication via header:
+
+```
+curl --header "PRIVATE-TOKEN: QVy1PB7sTxfy4pqfZM1U" --header "SUDO: username" "http://example.com/api/v3/projects"
+```
+```
+curl --header "PRIVATE-TOKEN: QVy1PB7sTxfy4pqfZM1U" --header "SUDO: 23" "http://example.com/api/v3/projects"
+```
 
 #### Pagination
 
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index f857d4133b2..996d3adb174 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -1,7 +1,41 @@
 module API
   module APIHelpers
+    PRIVATE_TOKEN_HEADER = "HTTP_PRIVATE_TOKEN"
+    PRIVATE_TOKEN_PARAM = :private_token
+    SUDO_HEADER ="HTTP_SUDO"
+    SUDO_PARAM = :sudo
+
     def current_user
-      @current_user ||= User.find_by_authentication_token(params[:private_token] || env["HTTP_PRIVATE_TOKEN"])
+      @current_user ||= User.find_by_authentication_token(params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER])
+      identifier = sudo_identifier()
+      # If the sudo is the current user do nothing
+      if (identifier && !(@current_user.id == identifier || @current_user.username == identifier))
+        render_api_error!('403 Forbidden: Must be admin to use sudo', 403) unless @current_user.is_admin?
+        begin
+
+          if (identifier.is_a?(Integer))
+            user = User.find_by_id(identifier)
+          else
+            user = User.find_by_username(identifier)
+          end
+          if user.nil?
+            not_found!("No user id or username for: #{identifier}")
+          end
+          @current_user = user
+        rescue => ex
+          not_found!("No user id or username for: #{identifier}")
+        end
+      end
+      @current_user
+    end
+
+    def sudo_identifier()
+      identifier = params[SUDO_PARAM] == nil ? env[SUDO_HEADER] : params[SUDO_PARAM]
+      if (!!(identifier =~ /^[0-9]+$/))
+        identifier.to_i
+      else
+        identifier
+      end
     end
 
     def user_project
@@ -95,10 +129,10 @@ module API
 
     def abilities
       @abilities ||= begin
-                       abilities = Six.new
-                       abilities << Ability
-                       abilities
-                     end
+        abilities = Six.new
+        abilities << Ability
+        abilities
+      end
     end
   end
 end
diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb
new file mode 100644
index 00000000000..de71deabb8e
--- /dev/null
+++ b/spec/requests/api/api_helpers_spec.rb
@@ -0,0 +1,159 @@
+require 'spec_helper'
+
+describe Gitlab::API do
+  include Gitlab::APIHelpers
+  include ApiHelpers
+  let(:user) { create(:user) }
+  let(:admin) { create(:admin) }
+  let(:key) { create(:key, user: user) }
+
+  let(:params) { {} }
+  let(:env) { {} }
+
+  def set_env(token_usr, identifier)
+    clear_env
+    clear_param
+    env[Gitlab::APIHelpers::PRIVATE_TOKEN_HEADER] = token_usr.private_token
+    env[Gitlab::APIHelpers::SUDO_HEADER] = identifier
+  end
+
+
+  def set_param(token_usr, identifier)
+    clear_env
+    clear_param
+    params[Gitlab::APIHelpers::PRIVATE_TOKEN_PARAM] = token_usr.private_token
+    params[Gitlab::APIHelpers::SUDO_PARAM] = identifier
+  end
+
+
+  def clear_env
+    env.delete(Gitlab::APIHelpers::PRIVATE_TOKEN_HEADER)
+    env.delete(Gitlab::APIHelpers::SUDO_HEADER)
+  end
+
+  def clear_param
+    params.delete(Gitlab::APIHelpers::PRIVATE_TOKEN_PARAM)
+    params.delete(Gitlab::APIHelpers::SUDO_PARAM)
+  end
+
+  def error!(message, status)
+    raise Exception
+  end
+
+  describe ".current_user" do
+    it "should leave user as is when sudo not specified" do
+      env[Gitlab::APIHelpers::PRIVATE_TOKEN_HEADER] = user.private_token
+      current_user.should == user
+      clear_env
+      params[Gitlab::APIHelpers::PRIVATE_TOKEN_PARAM] = user.private_token
+      current_user.should == user
+    end
+
+    it "should change current user to sudo when admin" do
+      set_env(admin, user.id)
+      current_user.should == user
+      set_param(admin, user.id)
+      current_user.should == user
+      set_env(admin, user.username)
+      current_user.should == user
+      set_param(admin, user.username)
+      current_user.should == user
+    end
+
+    it "should throw an error when the current user is not an admin and attempting to sudo" do
+      set_env(user, admin.id)
+      expect { current_user }.to raise_error
+      set_param(user, admin.id)
+      expect { current_user }.to raise_error
+      set_env(user, admin.username)
+      expect { current_user }.to raise_error
+      set_param(user, admin.username)
+      expect { current_user }.to raise_error
+    end
+    it "should throw an error when the user cannot be found for a given id" do
+      id = user.id + admin.id
+      user.id.should_not == id
+      admin.id.should_not == id
+      set_env(admin, id)
+      expect { current_user }.to raise_error
+
+      set_param(admin, id)
+      expect { current_user }.to raise_error
+    end
+    it "should throw an error when the user cannot be found for a given username" do
+      username = "#{user.username}#{admin.username}"
+      user.username.should_not == username
+      admin.username.should_not == username
+      set_env(admin, username)
+      expect { current_user }.to raise_error
+
+      set_param(admin, username)
+      expect { current_user }.to raise_error
+    end
+    it "should handle sudo's to oneself" do
+      set_env(admin, admin.id)
+      current_user.should == admin
+      set_param(admin, admin.id)
+      current_user.should == admin
+      set_env(admin, admin.username)
+      current_user.should == admin
+      set_param(admin, admin.username)
+      current_user.should == admin
+    end
+
+    it "should handle multiple sudo's to oneself" do
+      set_env(admin, user.id)
+      current_user.should == user
+      current_user.should == user
+      set_env(admin, user.username)
+      current_user.should == user
+      current_user.should == user
+
+      set_param(admin, user.id)
+      current_user.should == user
+      current_user.should == user
+      set_param(admin, user.username)
+      current_user.should == user
+      current_user.should == user
+    end
+    it "should handle multiple sudo's to oneself using string ids" do
+      set_env(admin, user.id.to_s)
+      current_user.should == user
+      current_user.should == user
+
+      set_param(admin, user.id.to_s)
+      current_user.should == user
+      current_user.should == user
+    end
+  end
+
+  describe '.sudo_identifier' do
+    it "should return integers when input is an int" do
+      set_env(admin, '123')
+      sudo_identifier.should == 123
+      set_env(admin, '0001234567890')
+      sudo_identifier.should == 1234567890
+
+      set_param(admin, '123')
+      sudo_identifier.should == 123
+      set_param(admin, '0001234567890')
+      sudo_identifier.should == 1234567890
+    end
+
+    it "should return string when input is an is not an int" do
+      set_env(admin, '12.30')
+      sudo_identifier.should == "12.30"
+      set_env(admin, 'hello')
+      sudo_identifier.should == 'hello'
+      set_env(admin, ' 123')
+      sudo_identifier.should == ' 123'
+
+      set_param(admin, '12.30')
+      sudo_identifier.should == "12.30"
+      set_param(admin, 'hello')
+      sudo_identifier.should == 'hello'
+      set_param(admin, ' 123')
+      sudo_identifier.should == ' 123'
+    end
+  end
+end
\ No newline at end of file
-- 
GitLab


From 3f73ea48ec7871c44ea1e791d6e31c2c7c8b852e Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Fri, 28 Jun 2013 08:59:05 -0400
Subject: [PATCH 051/248] Some of the requested updates, rebase on master

Change-Id: I305266fe9acbbb5136adeeb52e7e4e1d6629a30a
---
 app/models/user.rb                    |  8 ++++++++
 lib/api/helpers.rb                    | 23 ++++++++---------------
 spec/models/user_spec.rb              | 10 ++++++++++
 spec/requests/api/api_helpers_spec.rb | 24 ++++++++++++------------
 4 files changed, 38 insertions(+), 27 deletions(-)

diff --git a/app/models/user.rb b/app/models/user.rb
index b593c22fde3..c2355eaab99 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -190,6 +190,14 @@ class User < ActiveRecord::Base
     def search query
       where("name LIKE :query OR email LIKE :query OR username LIKE :query", query: "%#{query}%")
     end
+
+    def by_username_or_id(name_or_id)
+      if (name_or_id.is_a?(Integer))
+        User.find_by_id(name_or_id)
+      else
+        User.find_by_username(name_or_id)
+      end
+    end
   end
 
   #
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 996d3adb174..4f189f35196 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -12,25 +12,18 @@ module API
       if (identifier && !(@current_user.id == identifier || @current_user.username == identifier))
         render_api_error!('403 Forbidden: Must be admin to use sudo', 403) unless @current_user.is_admin?
         begin
-
-          if (identifier.is_a?(Integer))
-            user = User.find_by_id(identifier)
-          else
-            user = User.find_by_username(identifier)
-          end
-          if user.nil?
-            not_found!("No user id or username for: #{identifier}")
-          end
-          @current_user = user
+          @current_user = User.by_username_or_id(identifier)
         rescue => ex
           not_found!("No user id or username for: #{identifier}")
         end
+        not_found!("No user id or username for: #{identifier}") if current_user.nil?
       end
       @current_user
     end
 
     def sudo_identifier()
-      identifier = params[SUDO_PARAM] == nil ? env[SUDO_HEADER] : params[SUDO_PARAM]
+      identifier ||= params[SUDO_PARAM] ||= env[SUDO_HEADER]
+      # Regex for integers
       if (!!(identifier =~ /^[0-9]+$/))
         identifier.to_i
       else
@@ -129,10 +122,10 @@ module API
 
     def abilities
       @abilities ||= begin
-        abilities = Six.new
-        abilities << Ability
-        abilities
-      end
+                       abilities = Six.new
+                       abilities << Ability
+                       abilities
+                     end
     end
   end
 end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 695f0ae6846..de06bf71dc1 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -208,4 +208,14 @@ describe User do
       user.can_create_group.should == false
     end
   end
+
+  describe 'by_username_or_id' do
+    let(:user1){create(:user, username: 'foo')}
+    it "should get the correct user" do
+      User.by_username_or_id(user1.id).should == user1
+      User.by_username_or_id('foo').should == user1
+      User.by_username_or_id(-1).should be_nil
+      User.by_username_or_id('bar').should be_nil
+    end
+  end
 end
diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb
index de71deabb8e..a1cbfcd60e9 100644
--- a/spec/requests/api/api_helpers_spec.rb
+++ b/spec/requests/api/api_helpers_spec.rb
@@ -1,7 +1,7 @@
 require 'spec_helper'
 
-describe Gitlab::API do
-  include Gitlab::APIHelpers
+describe API do
+  include API::APIHelpers
   include ApiHelpers
   let(:user) { create(:user) }
   let(:admin) { create(:admin) }
@@ -13,27 +13,27 @@ describe Gitlab::API do
   def set_env(token_usr, identifier)
     clear_env
     clear_param
-    env[Gitlab::APIHelpers::PRIVATE_TOKEN_HEADER] = token_usr.private_token
-    env[Gitlab::APIHelpers::SUDO_HEADER] = identifier
+    env[API::APIHelpers::PRIVATE_TOKEN_HEADER] = token_usr.private_token
+    env[API::APIHelpers::SUDO_HEADER] = identifier
   end
 
 
   def set_param(token_usr, identifier)
     clear_env
     clear_param
-    params[Gitlab::APIHelpers::PRIVATE_TOKEN_PARAM] = token_usr.private_token
-    params[Gitlab::APIHelpers::SUDO_PARAM] = identifier
+    params[API::APIHelpers::PRIVATE_TOKEN_PARAM] = token_usr.private_token
+    params[API::APIHelpers::SUDO_PARAM] = identifier
   end
 
 
   def clear_env
-    env.delete(Gitlab::APIHelpers::PRIVATE_TOKEN_HEADER)
-    env.delete(Gitlab::APIHelpers::SUDO_HEADER)
+    env.delete(API::APIHelpers::PRIVATE_TOKEN_HEADER)
+    env.delete(API::APIHelpers::SUDO_HEADER)
   end
 
   def clear_param
-    params.delete(Gitlab::APIHelpers::PRIVATE_TOKEN_PARAM)
-    params.delete(Gitlab::APIHelpers::SUDO_PARAM)
+    params.delete(API::APIHelpers::PRIVATE_TOKEN_PARAM)
+    params.delete(API::APIHelpers::SUDO_PARAM)
   end
 
   def error!(message, status)
@@ -42,10 +42,10 @@ describe Gitlab::API do
 
   describe ".current_user" do
     it "should leave user as is when sudo not specified" do
-      env[Gitlab::APIHelpers::PRIVATE_TOKEN_HEADER] = user.private_token
+      env[API::APIHelpers::PRIVATE_TOKEN_HEADER] = user.private_token
       current_user.should == user
       clear_env
-      params[Gitlab::APIHelpers::PRIVATE_TOKEN_PARAM] = user.private_token
+      params[API::APIHelpers::PRIVATE_TOKEN_PARAM] = user.private_token
       current_user.should == user
     end
 
-- 
GitLab


From d48805ba35ea5502a44e6e20be663133f44995e3 Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Mon, 9 Sep 2013 13:18:10 -0400
Subject: [PATCH 052/248] Style guide fixes (spacing)

Change-Id: I966bfd0ccc4b05925384ecab8c6cbe3c6ba3b667
---
 spec/requests/api/api_helpers_spec.rb | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb
index a1cbfcd60e9..2fc78a7e390 100644
--- a/spec/requests/api/api_helpers_spec.rb
+++ b/spec/requests/api/api_helpers_spec.rb
@@ -17,7 +17,6 @@ describe API do
     env[API::APIHelpers::SUDO_HEADER] = identifier
   end
 
-
   def set_param(token_usr, identifier)
     clear_env
     clear_param
@@ -25,7 +24,6 @@ describe API do
     params[API::APIHelpers::SUDO_PARAM] = identifier
   end
 
-
   def clear_env
     env.delete(API::APIHelpers::PRIVATE_TOKEN_HEADER)
     env.delete(API::APIHelpers::SUDO_HEADER)
@@ -70,6 +68,7 @@ describe API do
       set_param(user, admin.username)
       expect { current_user }.to raise_error
     end
+
     it "should throw an error when the user cannot be found for a given id" do
       id = user.id + admin.id
       user.id.should_not == id
@@ -80,6 +79,7 @@ describe API do
       set_param(admin, id)
       expect { current_user }.to raise_error
     end
+
     it "should throw an error when the user cannot be found for a given username" do
       username = "#{user.username}#{admin.username}"
       user.username.should_not == username
@@ -90,6 +90,7 @@ describe API do
       set_param(admin, username)
       expect { current_user }.to raise_error
     end
+
     it "should handle sudo's to oneself" do
       set_env(admin, admin.id)
       current_user.should == admin
@@ -116,6 +117,7 @@ describe API do
       current_user.should == user
       current_user.should == user
     end
+
     it "should handle multiple sudo's to oneself using string ids" do
       set_env(admin, user.id.to_s)
       current_user.should == user
-- 
GitLab


From e7e1d76a2d0dfcabd3b7b0a36ddc69bc8b9f8661 Mon Sep 17 00:00:00 2001
From: Angus MacArthur <amacarthur@blackberry.com>
Date: Mon, 9 Sep 2013 01:45:30 -0400
Subject: [PATCH 053/248] make public/private setting for project creation
 configurable

---
 app/contexts/projects/create_context.rb       |  3 +-
 config/gitlab.yml.example                     |  3 +-
 config/initializers/1_settings.rb             |  1 +
 spec/contexts/projects_create_context_spec.rb | 28 +++++++++++++++++++
 4 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/app/contexts/projects/create_context.rb b/app/contexts/projects/create_context.rb
index 1ee3e459074..9fd24e0eeea 100644
--- a/app/contexts/projects/create_context.rb
+++ b/app/contexts/projects/create_context.rb
@@ -16,7 +16,8 @@ module Projects
         wiki_enabled: default_features.wiki,
         wall_enabled: default_features.wall,
         snippets_enabled: default_features.snippets,
-        merge_requests_enabled: default_features.merge_requests
+        merge_requests_enabled: default_features.merge_requests,
+        public: default_features.public
       }
 
       @project = Project.new(default_opts.merge(params))
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 7e1dacc5fa2..0d68879da6d 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -58,7 +58,8 @@ production: &base
       wiki: true
       wall: false
       snippets: false
-	  
+      public: false
+
     ## Webhook settings
     # Number of seconds to wait for HTTP response after sending webhook HTTP POST request (default: 10)
     # webhook_timeout: 10
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index a00768ed2d9..1c528ef4907 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -76,6 +76,7 @@ Settings.gitlab.default_projects_features['merge_requests'] = true if Settings.g
 Settings.gitlab.default_projects_features['wiki']           = true if Settings.gitlab.default_projects_features['wiki'].nil?
 Settings.gitlab.default_projects_features['wall']           = false if Settings.gitlab.default_projects_features['wall'].nil?
 Settings.gitlab.default_projects_features['snippets']       = false if Settings.gitlab.default_projects_features['snippets'].nil?
+Settings.gitlab.default_projects_features['public']         = false if Settings.gitlab.default_projects_features['public'].nil?
 
 #
 # Gravatar
diff --git a/spec/contexts/projects_create_context_spec.rb b/spec/contexts/projects_create_context_spec.rb
index dd10dd3ede8..3cabec283d7 100644
--- a/spec/contexts/projects_create_context_spec.rb
+++ b/spec/contexts/projects_create_context_spec.rb
@@ -30,6 +30,34 @@ describe Projects::CreateContext do
       it { @project.owner.should == @user }
       it { @project.namespace.should == @group }
     end
+
+    context 'respect configured public setting' do
+      before(:each) do
+        @settings = double("settings")
+        @settings.stub(:issues) { true }
+        @settings.stub(:merge_requests) { true }
+        @settings.stub(:wiki) { true }
+        @settings.stub(:wall) { true }
+        @settings.stub(:snippets) { true }
+        stub_const("Settings", Class.new)
+        Settings.stub_chain(:gitlab, :default_projects_features).and_return(@settings)
+      end
+      context 'should be public when setting is public' do
+        before do
+          @settings.stub(:public) { true }
+          @project = create_project(@user, @opts)
+        end
+        it { @project.public.should be_true }
+      end
+      context 'should be private when setting is not public' do
+        before do
+          @settings.stub(:public) { false }
+          @project = create_project(@user, @opts)
+        end
+        it { @project.public.should be_false }
+      end
+
+    end
   end
 
   def create_project(user, opts)
-- 
GitLab


From 063ba7819e03ffd9df6abbce812973e13755498e Mon Sep 17 00:00:00 2001
From: Angus MacArthur <amacarthur@blackberry.com>
Date: Mon, 9 Sep 2013 16:26:27 -0400
Subject: [PATCH 054/248] update to project creation page to reflect default
 public project setting

---
 app/views/projects/new.html.haml | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index 736da85952a..ab8efe5e3e1 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -2,8 +2,12 @@
   .project-edit-errors
     = render 'projects/errors'
   .project-edit-content
-    %p.slead
-      New projects are private by default. You choose who can see the project and commit to repository.
+    - if Gitlab.config.gitlab.default_projects_features.public
+      %p.slead
+        New projects are public by default. Any signed in user can see your project but cannot commit to it unless granted access.
+    - else
+      %p.slead
+        New projects are private by default. You choose who can see the project and commit to repository.
     %hr
     = form_for @project, remote: true do |f|
       .control-group.project-name-holder
-- 
GitLab


From 38cfd00e9d821dc284f72159bd14057297268a2b Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 10 Sep 2013 10:17:15 +0300
Subject: [PATCH 055/248] Improve commits list UI

---
 app/assets/stylesheets/sections/commits.scss  | 108 ++++++++----------
 app/views/projects/commits/_commit.html.haml  |  24 ++--
 app/views/projects/commits/_commits.html.haml |   1 +
 3 files changed, 58 insertions(+), 75 deletions(-)

diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
index 2f4472a52e1..f661276fcaa 100644
--- a/app/assets/stylesheets/sections/commits.scss
+++ b/app/assets/stylesheets/sections/commits.scss
@@ -345,46 +345,6 @@
 }
 
 
-/**
- * COMMIT ROW
- */
-.commit {
-  .browse_code_link_holder {
-    float: right;
-  }
-
-  .committed_ago {
-    float: right;
-    @extend .cgray;
-  }
-
-  .notes_count {
-    float: right;
-    margin-right: 10px;
-  }
-
-  code {
-    background: #FCEEC1;
-    color: $style_color;
-  }
-
-  .commit_short_id {
-    float: left;
-    @extend .lined;
-    min-width: 65px;
-    font-family: $monospace_font;
-  }
-
-  .row_title {
-    font-weight: bold;
-    color: #444;
-    &:hover {
-      color: #444;
-      text-decoration: underline;
-    }
-  }
-}
-
 .file-stats a {
   color: $style_color;
 }
@@ -472,24 +432,6 @@
   line-height: 2;
 }
 
-li.commit {
-  .avatar {
-    width: 24px;
-    top:-5px;
-    margin-right: 5px;
-    margin-left: 10px;
-  }
-
-  code {
-    padding: 2px 2px 0;
-    margin-top: -2px;
-    &:hover {
-      color: black;
-      border: 1px solid #ccc;
-    }
-  }
-}
-
 .commit-breadcrumb {
   padding: 0;
 }
@@ -506,8 +448,50 @@ li.commit {
   }
 }
 
-.commits-row {
-  padding-bottom: 10px;
-  margin-bottom: 10px;
-  border-bottom: 1px solid #DDD;
+.lists-separator {
+  margin: 10px 0;
+  border-top: 1px dashed #CCC;
+}
+
+/**
+ * COMMIT ROW
+ */
+li.commit {
+  padding: 8px;
+
+  .commit-row-title {
+    font-size: 14px;
+    margin-bottom: 2px;
+
+    .notes_count {
+      float: right;
+      margin-right: 10px;
+    }
+
+    .commit_short_id {
+      float: left;
+      min-width: 65px;
+      font-family: $monospace_font;
+    }
+
+    .commit-row-message {
+      color: #555;
+      font-weight: bolder;
+      &:hover {
+        color: #444;
+        text-decoration: underline;
+      }
+    }
+  }
+
+  .commit-row-info {
+    a {
+      color: #777;
+    }
+
+    .committed_ago {
+      float: right;
+      @extend .cgray;
+    }
+  }
 }
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index eb5bdb886e2..d70fd96accd 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -1,21 +1,19 @@
 %li.commit
-  .browse_code_link_holder
-    %p
-      %strong= link_to "Browse Code »", project_tree_path(project, commit), class: "right"
-  %p
+  .commit-row-title
     = link_to commit.short_id(8), project_commit_path(project, commit), class: "commit_short_id"
-    = commit_author_link(commit, avatar: true, size: 24)
     &nbsp;
-    = link_to_gfm truncate(commit.title, length: 70), project_commit_path(project, commit.id), class: "row_title"
-
-    %time.committed_ago{ datetime: commit.committed_date, title: commit.committed_date.stamp("Aug 21, 2011 9:23pm") }
-      = time_ago_in_words(commit.committed_date)
-      ago
-      &nbsp;
-
-    %span.notes_count
+    = link_to_gfm truncate(commit.title, length: 70), project_commit_path(project, commit.id), class: "commit-row-message"
+    = link_to "Browse Code »", project_tree_path(project, commit), class: "pull-right"
+    .notes_count
       - notes = project.notes.for_commit_id(commit.id)
       - if notes.any?
         %span.badge.badge-info
           %i.icon-comment
           = notes.count
+
+  .commit-row-info
+    = commit_author_link(commit, avatar: true, size: 16)
+    %time.committed_ago{ datetime: commit.committed_date, title: commit.committed_date.stamp("Aug 21, 2011 9:23pm") }
+      = time_ago_in_words(commit.committed_date)
+      ago
+      &nbsp;
diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml
index b6eeeb92287..b6404778073 100644
--- a/app/views/projects/commits/_commits.html.haml
+++ b/app/views/projects/commits/_commits.html.haml
@@ -8,3 +8,4 @@
     .span10
       %ul.well-list
         = render commits, project: @project
+  %hr.lists-separator
-- 
GitLab


From 845a3419b5c1211a01086f964867680df77f828e Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 10 Sep 2013 13:15:49 +0300
Subject: [PATCH 056/248] UI fixes for commits lists

---
 app/assets/stylesheets/sections/commits.scss    | 12 +++++++++++-
 app/assets/stylesheets/sections/events.scss     | 17 ++++-------------
 .../stylesheets/sections/merge_requests.scss    |  7 -------
 app/helpers/commits_helper.rb                   |  5 +++--
 app/views/events/_commit.html.haml              |  8 +++-----
 .../projects/commits/_inline_commit.html.haml   |  9 +++++++++
 6 files changed, 30 insertions(+), 28 deletions(-)
 create mode 100644 app/views/projects/commits/_inline_commit.html.haml

diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
index f661276fcaa..b0cf8b16260 100644
--- a/app/assets/stylesheets/sections/commits.scss
+++ b/app/assets/stylesheets/sections/commits.scss
@@ -469,7 +469,6 @@ li.commit {
     }
 
     .commit_short_id {
-      float: left;
       min-width: 65px;
       font-family: $monospace_font;
     }
@@ -494,4 +493,15 @@ li.commit {
       @extend .cgray;
     }
   }
+
+  &.inline-commit {
+    .commit-row-title {
+      font-size: 13px;
+    }
+
+    .committed_ago {
+      float: right;
+      @extend .cgray;
+    }
+  }
 }
diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss
index 80ee6b6323c..fd5c80f988c 100644
--- a/app/assets/stylesheets/sections/events.scss
+++ b/app/assets/stylesheets/sections/events.scss
@@ -56,10 +56,6 @@
     margin-left: 35px;
     margin-right: 100px;
 
-    .commit p {
-      color: #666;
-      padding-top: 5px;
-    }
     .event-info {
       color: #666;
     }
@@ -107,13 +103,6 @@
     }
   }
 
-  ul {
-    .avatar {
-      width: 18px;
-      margin: 2px 4px;
-    }
-  }
-
   &:last-child { border:none }
 
   .event_commits {
@@ -124,12 +113,14 @@
         background: transparent;
         padding: 3px;
         border: none;
-        font-size: 12px;
+        color: #666;
+        .commit-row-title {
+          font-size: 12px;
+        }
       }
       &.commits-stat {
         display: block;
         padding: 3px;
-        margin-top: 3px;
 
         &:hover {
           background: none;
diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss
index e7b464fd4aa..aa61cae4b9a 100644
--- a/app/assets/stylesheets/sections/merge_requests.scss
+++ b/app/assets/stylesheets/sections/merge_requests.scss
@@ -64,13 +64,6 @@
     margin: 0;
     padding: 0;
     padding: 5px 0;
-    .avatar { position:relative }
-    .commit-author-name,
-    .dash,
-    .committed_ago,
-    .browse_code_link_holder {
-      display: none;
-    }
     list-style: none;
     &:hover {
       background: none;
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index e889b390968..f8f84ff8b62 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -56,8 +56,9 @@ module CommitsHelper
     end
   end
 
-  def commit_to_html commit, project
-    escape_javascript(render 'projects/commits/commit', commit: commit, project: project) unless commit.nil?
+  def commit_to_html(commit, project, inline = true)
+    template = inline ? "inline_commit" : "commit"
+    escape_javascript(render "projects/commits/#{template}", commit: commit, project: project) unless commit.nil?
   end
 
   def diff_line_content(line)
diff --git a/app/views/events/_commit.html.haml b/app/views/events/_commit.html.haml
index b50faf5a25c..4d4b24009f4 100644
--- a/app/views/events/_commit.html.haml
+++ b/app/views/events/_commit.html.haml
@@ -1,7 +1,5 @@
 %li.commit
-  %p
+  .commit-row-title
     = link_to commit[:id][0..8], project_commit_path(project, commit[:id]), class: "commit_short_id", alt: ''
-    %span= commit[:author][:name]
-    &ndash;
-    = image_tag gravatar_icon(commit[:author][:email]), class: "avatar", width: 16
-    = gfm escape_once(truncate(commit[:message], length: 50)) rescue "--broken encoding"
+    &nbsp;
+    = gfm escape_once(truncate(commit[:message], length: 70)) rescue "--broken encoding"
diff --git a/app/views/projects/commits/_inline_commit.html.haml b/app/views/projects/commits/_inline_commit.html.haml
new file mode 100644
index 00000000000..5be8460e061
--- /dev/null
+++ b/app/views/projects/commits/_inline_commit.html.haml
@@ -0,0 +1,9 @@
+%li.commit.inline-commit
+  .commit-row-title
+    = link_to commit.short_id(8), project_commit_path(project, commit), class: "commit_short_id"
+    &nbsp;
+    = link_to_gfm truncate(commit.title, length: 40), project_commit_path(project, commit.id), class: "commit-row-message"
+    %time.committed_ago{ datetime: commit.committed_date, title: commit.committed_date.stamp("Aug 21, 2011 9:23pm") }
+      = time_ago_in_words(commit.committed_date)
+      ago
+      &nbsp;
-- 
GitLab


From c962dd247312742d8434caf53b7462caaba17daf Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 10 Sep 2013 13:37:56 +0300
Subject: [PATCH 057/248] More entries in CHANGELOG for 6.1

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

diff --git a/CHANGELOG b/CHANGELOG
index e843c180cd8..5c27e93ff64 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,9 +1,15 @@
 v 6.1.0
+  - Description field added to Merge Request
+  - API: Sudo api calls (Izaak Alpert)
+  - API: Group membership api (Izaak Alpert)
+  - Improved commit diff
+  - Improved large commit handling (Boyan Tabakov)
   - Rewrite: Init script now less prone to errors and keeps better track of the service.
   - Link issues, merge requests, and commits when they reference each other with GFM
   - Close issues automatically when pushing commits with a special message
   - Project internal ids for issues, mr, milestones
   - Improve user removal from admin area
+  - Invalidate events cache when project was moved
   - Remove deprecated classes and rake tasks
   - Add event filter for group and project show pages
   - Add links to create branch/tag from project home page
-- 
GitLab


From 2c72fd461c275d5445f72b56ecf3e45348905b15 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 10 Sep 2013 13:42:53 +0300
Subject: [PATCH 058/248] Clear cache when update to 6.1

---
 doc/update/6.0-to-6.1.md | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/doc/update/6.0-to-6.1.md b/doc/update/6.0-to-6.1.md
index c9a3a31fd27..dcd09be72f7 100644
--- a/doc/update/6.0-to-6.1.md
+++ b/doc/update/6.0-to-6.1.md
@@ -54,12 +54,13 @@ sudo -u git -H bundle install --without development test mysql --deployment
 sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
 sudo -u git -H bundle exec rake migrate_iids RAILS_ENV=production
 sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
 ```
 
 ### 5. Update config files
 
-* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/5-4-stable/config/gitlab.yml.example but with your settings.
-* Make `/home/git/gitlab/config/unicorn.rb` same as https://github.com/gitlabhq/gitlabhq/blob/5-4-stable/config/unicorn.rb.example but with your settings.
+* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/6-1-stable/config/gitlab.yml.example but with your settings.
+* Make `/home/git/gitlab/config/unicorn.rb` same as https://github.com/gitlabhq/gitlabhq/blob/6-1-stable/config/unicorn.rb.example but with your settings.
 
 ### 6. Update Init script
 
-- 
GitLab


From dc1c0b20e116b5b7d2f5499c3fc284081dd5e03e Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 10 Sep 2013 13:43:06 +0300
Subject: [PATCH 059/248] Version up to beta1

---
 VERSION | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/VERSION b/VERSION
index ce3de583065..f5999028a39 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-6.1.0.pre
+6.1.0.beta1
-- 
GitLab


From c6a5c5736d96dbad25de3ee73d86344c1c5907f0 Mon Sep 17 00:00:00 2001
From: Angus MacArthur <amacarthur@blackberry.com>
Date: Tue, 10 Sep 2013 10:49:23 -0400
Subject: [PATCH 060/248] style fixes

---
 spec/contexts/projects_create_context_spec.rb | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/spec/contexts/projects_create_context_spec.rb b/spec/contexts/projects_create_context_spec.rb
index 3cabec283d7..be492585b27 100644
--- a/spec/contexts/projects_create_context_spec.rb
+++ b/spec/contexts/projects_create_context_spec.rb
@@ -42,21 +42,24 @@ describe Projects::CreateContext do
         stub_const("Settings", Class.new)
         Settings.stub_chain(:gitlab, :default_projects_features).and_return(@settings)
       end
+
       context 'should be public when setting is public' do
         before do
           @settings.stub(:public) { true }
           @project = create_project(@user, @opts)
         end
+
         it { @project.public.should be_true }
       end
+
       context 'should be private when setting is not public' do
         before do
           @settings.stub(:public) { false }
           @project = create_project(@user, @opts)
         end
+
         it { @project.public.should be_false }
       end
-
     end
   end
 
-- 
GitLab


From b16e82f5d7fae62bed874e309ad4babdc63f69ae Mon Sep 17 00:00:00 2001
From: Stephen Holdaway <stecman@gmail.com>
Date: Thu, 12 Sep 2013 00:10:45 +1200
Subject: [PATCH 061/248] Fix several_namespaces? to work with multiple
 ownership of groups

---
 app/models/user.rb       |  2 +-
 spec/models/user_spec.rb | 13 +++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/app/models/user.rb b/app/models/user.rb
index c2355eaab99..2411b270fc6 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -322,7 +322,7 @@ class User < ActiveRecord::Base
   end
 
   def several_namespaces?
-    namespaces.many?
+    namespaces.many? || owned_groups.any?
   end
 
   def namespace_id
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index de06bf71dc1..d79d2b82b6a 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -139,6 +139,19 @@ describe User do
     it { @user.owned_groups.should == [@group] }
   end
 
+  describe 'group multiple owners' do
+    before do
+      ActiveRecord::Base.observers.enable(:user_observer)
+      @user = create :user
+      @user2 = create :user
+      @group = create :group, owner: @user
+
+      @group.add_users([@user2.id], UsersGroup::OWNER)
+    end
+
+    it { @user2.several_namespaces?.should be_true }
+  end
+
   describe 'namespaced' do
     before do
       ActiveRecord::Base.observers.enable(:user_observer)
-- 
GitLab


From 7b99681836deebcb98633341f70424049729c635 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 11 Sep 2013 20:27:50 +0300
Subject: [PATCH 062/248] Fix feature test

---
 features/steps/project/project_forked_merge_requests.rb | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/features/steps/project/project_forked_merge_requests.rb b/features/steps/project/project_forked_merge_requests.rb
index 86f16d3bac5..f7bf085a423 100644
--- a/features/steps/project/project_forked_merge_requests.rb
+++ b/features/steps/project/project_forked_merge_requests.rb
@@ -175,10 +175,9 @@ class ProjectForkedMergeRequests < Spinach::FeatureSteps
     @project ||= Project.find_by_name!("Shop")
   end
 
-  #Verify a link is generated against the correct project
+  # Verify a link is generated against the correct project
   def verify_commit_link(container_div, container_project)
-    #This should force a wait for the javascript to execute
-    find(:div,container_div).should have_css ".browse_code_link_holder"
+    # This should force a wait for the javascript to execute
     find(:div,container_div).find(".commit_short_id")['href'].should have_content "#{container_project.path_with_namespace}/commit"
   end
 end
-- 
GitLab


From 9ad75248b869626fd1aefbdc3e3cfd89589e0150 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 11 Sep 2013 21:00:16 +0300
Subject: [PATCH 063/248] Fix 404 if Group guest visit empty group page

---
 app/controllers/groups_controller.rb | 2 +-
 app/models/ability.rb                | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 3378675692a..9dc9afe9e67 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -110,7 +110,7 @@ class GroupsController < ApplicationController
 
   # Dont allow unauthorized access to group
   def authorize_read_group!
-    unless projects.present? or can?(current_user, :manage_group, @group)
+    unless projects.present? or can?(current_user, :read_group, @group)
       return render_404
     end
   end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 74f92fe7438..8335829f919 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -135,6 +135,10 @@ class Ability
     def group_abilities user, group
       rules = []
 
+      if group.users.include?(user)
+        rules << :read_group
+      end
+
       # Only group owner and administrators can manage group
       if group.owners.include?(user) || user.admin?
         rules << [
-- 
GitLab


From ab916d3251f5ed5e363ca3896e91c078eac5da95 Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Thu, 8 Aug 2013 14:09:33 -0400
Subject: [PATCH 064/248] Update User api to respect default settings

-API now respects default_projects_limit, default_can_create_group, and default_can_create_team

Change-Id: I059d060d576df1050e5371e707381c5e8c608a7a
---
 app/models/user.rb              |  5 +++++
 lib/api/users.rb                |  2 +-
 spec/requests/api/users_spec.rb | 11 +++++++++++
 3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/app/models/user.rb b/app/models/user.rb
index 2411b270fc6..526edb9839e 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -198,6 +198,11 @@ class User < ActiveRecord::Base
         User.find_by_username(name_or_id)
       end
     end
+
+    def defaults
+      { projects_limit: Gitlab.config.gitlab.default_projects_limit, can_create_group: Gitlab.config.gitlab.default_can_create_group, can_create_team: Gitlab.config.gitlab.default_can_create_team }
+    end
+
   end
 
   #
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 84256b51124..3b7ae9f01a1 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -46,7 +46,7 @@ module API
         authenticated_as_admin!
         required_attributes! [:email, :password, :name, :username]
 
-        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
+        attrs = User.defaults.merge(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
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 2f4aaae3890..c09d78993e1 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -57,6 +57,17 @@ describe API::API do
       response.status.should == 201
     end
 
+    it "creating a user should respect default project limit" do
+      limit = 123456
+      Gitlab.config.gitlab.stub(:default_projects_limit).and_return(limit)
+      attr = attributes_for(:user )
+      expect {
+        post api("/users", admin), attr
+      }.to change { User.count }.by(1)
+      User.find_by_username(attr[:username]).projects_limit.should == limit
+      Gitlab.config.gitlab.unstub(:default_projects_limit)
+    end
+
     it "should not create user with invalid email" do
       post api("/users", admin), { email: "invalid email", password: 'password' }
       response.status.should == 400
-- 
GitLab


From dc5578307671324e65eb809d31a45e773ebc0105 Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Thu, 15 Aug 2013 17:43:46 -0400
Subject: [PATCH 065/248] Update to only provide one way to get a default user

-calling build_user will now apply defaults and only override them if as: :admin is set

Change-Id: Id1d938c0967752ecc14370af54f2d88128d18c44
---
 app/controllers/admin/users_controller.rb |  4 +-
 app/models/user.rb                        | 27 +++++----
 lib/api/users.rb                          |  5 +-
 lib/gitlab/auth.rb                        | 66 +++++++++++++++++++++
 spec/models/user_spec.rb                  | 72 +++++++++++++++++------
 spec/requests/api/users_spec.rb           |  4 +-
 6 files changed, 143 insertions(+), 35 deletions(-)

diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 7809a157dbc..70bbe306562 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -13,7 +13,7 @@ class Admin::UsersController < Admin::ApplicationController
   end
 
   def new
-    @user = User.new.with_defaults
+    @user = User.build_user
   end
 
   def edit
@@ -44,7 +44,7 @@ class Admin::UsersController < Admin::ApplicationController
       password_expires_at: Time.now
     }
 
-    @user = User.new(params[:user].merge(opts), as: :admin)
+    @user = User.build_user(params[:user].merge(opts), as: :admin)
     @user.admin = (admin && admin.to_i > 0)
     @user.created_by_id = current_user.id
 
diff --git a/app/models/user.rb b/app/models/user.rb
index 526edb9839e..fbcc004f9b0 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -199,10 +199,16 @@ class User < ActiveRecord::Base
       end
     end
 
-    def defaults
-      { projects_limit: Gitlab.config.gitlab.default_projects_limit, can_create_group: Gitlab.config.gitlab.default_can_create_group, can_create_team: Gitlab.config.gitlab.default_can_create_team }
+    def build_user(attrs = {}, options= {})
+      user = User.new(defaults.merge(attrs), options)
+      # if not as: :admin force default settings
+      user.with_defaults unless options[:as] == :admin
+      user
     end
 
+    def defaults
+      { projects_limit: Gitlab.config.gitlab.default_projects_limit, can_create_group: Gitlab.config.gitlab.default_can_create_group, theme_id: Gitlab::Theme::BASIC }
+    end
   end
 
   #
@@ -213,14 +219,6 @@ class User < ActiveRecord::Base
     username
   end
 
-  def with_defaults
-    tap do |u|
-      u.projects_limit = Gitlab.config.gitlab.default_projects_limit
-      u.can_create_group = Gitlab.config.gitlab.default_can_create_group
-      u.theme_id = Gitlab::Theme::MARS
-    end
-  end
-
   def notification
     @notification ||= Notification.new(self)
   end
@@ -380,4 +378,13 @@ class User < ActiveRecord::Base
       group.owners == [self]
     end
   end
+
+  :private
+
+  def with_defaults
+    User.defaults.each do |k,v|
+      self.send("#{k}=",v)
+    end
+  end
+
 end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 3b7ae9f01a1..00dc2311ffd 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -45,9 +45,8 @@ module API
       post do
         authenticated_as_admin!
         required_attributes! [:email, :password, :name, :username]
-
-        attrs = User.defaults.merge(attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio])
-        user = User.new attrs, as: :admin
+        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
+        user = User.build_user(attrs, as: :admin)
         if user.save
           present user, with: Entities::User
         else
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 0f196297477..b1e40defc7f 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -13,6 +13,72 @@ module Gitlab
       end
     end
 
+    def find_for_ldap_auth(auth, signed_in_resource = nil)
+      uid = auth.info.uid
+      provider = auth.provider
+      email = auth.info.email.downcase unless auth.info.email.nil?
+      raise OmniAuth::Error, "LDAP accounts must provide an uid and email address" if uid.nil? or email.nil?
+
+      if @user = User.find_by_extern_uid_and_provider(uid, provider)
+        @user
+      elsif @user = User.find_by_email(email)
+        log.info "Updating legacy LDAP user #{email} with extern_uid => #{uid}"
+        @user.update_attributes(extern_uid: uid, provider: provider)
+        @user
+      else
+        create_from_omniauth(auth, true)
+      end
+    end
+
+    def create_from_omniauth(auth, ldap = false)
+      provider = auth.provider
+      uid = auth.info.uid || auth.uid
+      uid = uid.to_s.force_encoding("utf-8")
+      name = auth.info.name.to_s.force_encoding("utf-8")
+      email = auth.info.email.to_s.downcase unless auth.info.email.nil?
+
+      ldap_prefix = ldap ? '(LDAP) ' : ''
+      raise OmniAuth::Error, "#{ldap_prefix}#{provider} does not provide an email"\
+        " address" if auth.info.email.blank?
+
+      log.info "#{ldap_prefix}Creating user from #{provider} login"\
+        " {uid => #{uid}, name => #{name}, email => #{email}}"
+      password = Devise.friendly_token[0, 8].downcase
+      @user = User.build_user({
+        extern_uid: uid,
+        provider: provider,
+        name: name,
+        username: email.match(/^[^@]*/)[0],
+        email: email,
+        password: password,
+        password_confirmation: password,
+      }, as: :admin)
+      @user.save!
+
+      if Gitlab.config.omniauth['block_auto_created_users'] && !ldap
+        @user.block
+      end
+
+      @user
+    end
+
+    def find_or_new_for_omniauth(auth)
+      provider, uid = auth.provider, auth.uid
+      email = auth.info.email.downcase unless auth.info.email.nil?
+
+      if @user = User.find_by_provider_and_extern_uid(provider, uid)
+        @user
+      elsif @user = User.find_by_email(email)
+        @user.update_attributes(extern_uid: uid, provider: provider)
+        @user
+      else
+        if Gitlab.config.omniauth['allow_single_sign_on']
+          @user = create_from_omniauth(auth)
+          @user
+        end
+      end
+    end
+
     def log
       Gitlab::AppLogger
     end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index d79d2b82b6a..330d22cf962 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -196,29 +196,63 @@ describe User do
     it { User.not_in_project(@project).should include(@user, @project.owner) }
   end
 
-  describe 'normal user' do
-    let(:user) { create(:user, name: 'John Smith') }
+  describe 'user creation' do
+    describe 'normal user' do
+      let(:user) { create(:user, name: 'John Smith') }
 
-    it { user.is_admin?.should be_false }
-    it { user.require_ssh_key?.should be_true }
-    it { user.can_create_group?.should be_true }
-    it { user.can_create_project?.should be_true }
-    it { user.first_name.should == 'John' }
-  end
+      it { user.is_admin?.should be_false }
+      it { user.require_ssh_key?.should be_true }
+      it { user.can_create_group?.should be_true }
+      it { user.can_create_project?.should be_true }
+      it { user.first_name.should == 'John' }
+    end
 
-  describe 'without defaults' do
-    let(:user) { User.new }
-    it "should not apply defaults to user" do
-      user.projects_limit.should == 10
-      user.can_create_group.should == true
+    describe 'without defaults' do
+      let(:user) { User.new }
+      it "should not apply defaults to user" do
+        user.projects_limit.should == 10
+        user.can_create_group.should be_true
+        user.theme_id.should == Gitlab::Theme::BASIC
+      end
     end
-  end
+    context 'as admin' do
+      describe 'with defaults' do
+        let(:user) { User.build_user({}, as: :admin) }
+        it "should apply defaults to user" do
+          user.projects_limit.should == 42
+          user.can_create_group.should be_false
+          user.theme_id.should == Gitlab::Theme::BASIC
+        end
+      end
+
+      describe 'with default overrides' do
+        let(:user) { User.build_user({projects_limit: 123, can_create_group: true, can_create_team: true, theme_id: Gitlab::Theme::MARS}, as: :admin) }
+        it "should apply defaults to user" do
+          user.projects_limit.should == 123
+          user.can_create_group.should be_true
+          user.theme_id.should == Gitlab::Theme::MARS
+        end
+      end
+    end
+
+    context 'as user' do
+      describe 'with defaults' do
+        let(:user) { User.build_user }
+        it "should apply defaults to user" do
+          user.projects_limit.should == 42
+          user.can_create_group.should be_false
+          user.theme_id.should == Gitlab::Theme::BASIC
+        end
+      end
 
-  describe 'with defaults' do
-    let(:user) { User.new.with_defaults }
-    it "should apply defaults to user" do
-      user.projects_limit.should == 42
-      user.can_create_group.should == false
+      describe 'with default overrides' do
+        let(:user) { User.build_user(projects_limit: 123, can_create_group: true, theme_id: Gitlab::Theme::MARS) }
+        it "should apply defaults to user" do
+          user.projects_limit.should == 42
+          user.can_create_group.should be_false
+          user.theme_id.should == Gitlab::Theme::BASIC
+        end
+      end
     end
   end
 
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index c09d78993e1..e42c0567ef6 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -64,7 +64,9 @@ describe API::API do
       expect {
         post api("/users", admin), attr
       }.to change { User.count }.by(1)
-      User.find_by_username(attr[:username]).projects_limit.should == limit
+      user = User.find_by_username(attr[:username])
+      user.projects_limit.should == limit
+      user.theme_id.should == Gitlab::Theme::BASIC
       Gitlab.config.gitlab.unstub(:default_projects_limit)
     end
 
-- 
GitLab


From 482d167b835c84b857f7dbf86d1b3f8f3460d39b Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Wed, 11 Sep 2013 12:23:04 -0400
Subject: [PATCH 066/248] Style updates

Change-Id: Ib4eb533dff5c722fe559330e4aa71b5d5baf6fb8
---
 app/models/user.rb | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/app/models/user.rb b/app/models/user.rb
index fbcc004f9b0..e92f0847724 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -207,7 +207,11 @@ class User < ActiveRecord::Base
     end
 
     def defaults
-      { projects_limit: Gitlab.config.gitlab.default_projects_limit, can_create_group: Gitlab.config.gitlab.default_can_create_group, theme_id: Gitlab::Theme::BASIC }
+      {
+        projects_limit: Gitlab.config.gitlab.default_projects_limit,
+        can_create_group: Gitlab.config.gitlab.default_can_create_group,
+        theme_id: Gitlab::Theme::BASIC
+      }
     end
   end
 
@@ -379,12 +383,11 @@ class User < ActiveRecord::Base
     end
   end
 
-  :private
+  private
 
   def with_defaults
     User.defaults.each do |k,v|
       self.send("#{k}=",v)
     end
   end
-
 end
-- 
GitLab


From 4e0c57b72f326f8723db642a0eb9c79e41302627 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 11 Sep 2013 21:12:33 +0300
Subject: [PATCH 067/248] Update poltergeist and database_cleaner

---
 Gemfile      |  2 +-
 Gemfile.lock | 17 +++++++++--------
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/Gemfile b/Gemfile
index 5b8118457d3..b201969bc36 100644
--- a/Gemfile
+++ b/Gemfile
@@ -187,7 +187,7 @@ group :development, :test do
   gem 'rb-inotify', require: linux_only('rb-inotify')
 
   # PhantomJS driver for Capybara
-  gem 'poltergeist', '~> 1.3.0'
+  gem 'poltergeist', '~> 1.4.1'
 
   gem 'spork', '~> 1.0rc'
   gem 'jasmine'
diff --git a/Gemfile.lock b/Gemfile.lock
index d71988e13e6..ddca83d38c2 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -72,6 +72,7 @@ GEM
       railties (>= 3.0)
       sass-rails (>= 3.2)
     chunky_png (1.2.8)
+    cliver (0.2.1)
     code_analyzer (0.3.2)
       sexp_processor
     coderay (1.0.9)
@@ -102,7 +103,7 @@ GEM
     d3_rails (3.1.10)
       railties (>= 3.1.0)
     daemons (1.1.9)
-    database_cleaner (1.0.1)
+    database_cleaner (1.1.1)
     debug_inspector (0.0.2)
     descendants_tracker (0.0.1)
     devise (2.2.5)
@@ -132,8 +133,6 @@ GEM
       multipart-post (~> 1.1)
     faraday_middleware (0.9.0)
       faraday (>= 0.7.4, < 0.9)
-    faye-websocket (0.4.7)
-      eventmachine (>= 0.12.0)
     ffaker (1.16.1)
     ffi (1.9.0)
     fog (1.3.1)
@@ -275,7 +274,7 @@ GEM
       mime-types (~> 1.16)
       treetop (~> 1.4.8)
     method_source (0.8.1)
-    mime-types (1.23)
+    mime-types (1.25)
     minitest (4.7.4)
     modernizr (2.6.2)
       sprockets (~> 2.0)
@@ -315,10 +314,11 @@ GEM
       omniauth-oauth (~> 1.0)
     orm_adapter (0.4.0)
     pg (0.15.1)
-    poltergeist (1.3.0)
+    poltergeist (1.4.1)
       capybara (~> 2.1.0)
-      faye-websocket (>= 0.4.4, < 0.5.0)
-      http_parser.rb (~> 0.5.3)
+      cliver (~> 0.2.1)
+      multi_json (~> 1.0)
+      websocket-driver (>= 0.2.0)
     polyglot (0.3.3)
     posix-spawn (0.3.6)
     pry (0.9.12.2)
@@ -534,6 +534,7 @@ GEM
       addressable (>= 2.2.7)
       crack (>= 0.3.2)
     websocket (1.0.7)
+    websocket-driver (0.3.0)
     xpath (2.0.0)
       nokogiri (~> 1.3)
     yajl-ruby (1.1.0)
@@ -599,7 +600,7 @@ DEPENDENCIES
   omniauth-google-oauth2
   omniauth-twitter
   pg
-  poltergeist (~> 1.3.0)
+  poltergeist (~> 1.4.1)
   pry
   quiet_assets (~> 1.0.1)
   rack-mini-profiler
-- 
GitLab


From 3c13408f2579868014f9d6fe845aae2cd5d154bd Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 11 Sep 2013 21:17:28 +0300
Subject: [PATCH 068/248] Email templates when user was added to group

---
 app/mailers/emails/groups.rb                      | 11 +++++++++++
 app/mailers/emails/profile.rb                     | 15 +++++++++++++++
 app/mailers/emails/projects.rb                    |  1 -
 app/mailers/notify.rb                             | 14 ++------------
 .../notify/group_access_granted_email.html.haml   |  5 +++++
 .../notify/group_access_granted_email.text.erb    |  4 ++++
 6 files changed, 37 insertions(+), 13 deletions(-)
 create mode 100644 app/mailers/emails/groups.rb
 create mode 100644 app/mailers/emails/profile.rb
 create mode 100644 app/views/notify/group_access_granted_email.html.haml
 create mode 100644 app/views/notify/group_access_granted_email.text.erb

diff --git a/app/mailers/emails/groups.rb b/app/mailers/emails/groups.rb
new file mode 100644
index 00000000000..2e9d28981e3
--- /dev/null
+++ b/app/mailers/emails/groups.rb
@@ -0,0 +1,11 @@
+module Emails
+  module Groups
+    def group_access_granted_email(user_group_id)
+      @membership = UsersGroup.find(user_group_id)
+      @group = @membership.group
+
+      mail(to: @membership.user.email,
+           subject: subject("access to group was granted"))
+    end
+  end
+end
diff --git a/app/mailers/emails/profile.rb b/app/mailers/emails/profile.rb
new file mode 100644
index 00000000000..bcd44f9476c
--- /dev/null
+++ b/app/mailers/emails/profile.rb
@@ -0,0 +1,15 @@
+module Emails
+  module Profile
+    def new_user_email(user_id, password)
+      @user = User.find(user_id)
+      @password = password
+      mail(to: @user.email, subject: subject("Account was created for you"))
+    end
+
+    def new_ssh_key_email(key_id)
+      @key = Key.find(key_id)
+      @user = @key.user
+      mail(to: @user.email, subject: subject("SSH key was added to your account"))
+    end
+  end
+end
diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb
index 1ad7ca588bd..4d5fe9ef614 100644
--- a/app/mailers/emails/projects.rb
+++ b/app/mailers/emails/projects.rb
@@ -7,7 +7,6 @@ module Emails
            subject: subject("access to project was granted"))
     end
 
-
     def project_was_moved_email(project_id, user_id)
       @user = User.find user_id
       @project = Project.find project_id
diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index 7890ca7793b..2f7be00c33e 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -3,6 +3,8 @@ class Notify < ActionMailer::Base
   include Emails::MergeRequests
   include Emails::Notes
   include Emails::Projects
+  include Emails::Profile
+  include Emails::Groups
 
   add_template_helper ApplicationHelper
   add_template_helper GitlabMarkdownHelper
@@ -20,18 +22,6 @@ class Notify < ActionMailer::Base
     delay_for(2.seconds)
   end
 
-  def new_user_email(user_id, password)
-    @user = User.find(user_id)
-    @password = password
-    mail(to: @user.email, subject: subject("Account was created for you"))
-  end
-
-  def new_ssh_key_email(key_id)
-    @key = Key.find(key_id)
-    @user = @key.user
-    mail(to: @user.email, subject: subject("SSH key was added to your account"))
-  end
-
   private
 
   # Look up a User by their ID and return their email address
diff --git a/app/views/notify/group_access_granted_email.html.haml b/app/views/notify/group_access_granted_email.html.haml
new file mode 100644
index 00000000000..5023ec737a5
--- /dev/null
+++ b/app/views/notify/group_access_granted_email.html.haml
@@ -0,0 +1,5 @@
+%p
+  = "You have been granted #{@membership.human_access} access to group"
+%p
+  = link_to group_url(@group) do
+    = @group.name
diff --git a/app/views/notify/group_access_granted_email.text.erb b/app/views/notify/group_access_granted_email.text.erb
new file mode 100644
index 00000000000..331bb98d5c9
--- /dev/null
+++ b/app/views/notify/group_access_granted_email.text.erb
@@ -0,0 +1,4 @@
+
+You have been granted <%= @membership.human_access %> access to group <%= @group.name %>
+
+<%= url_for(group_url(@group)) %>
-- 
GitLab


From b7b835900a9e72dddb756d47dae80d2943770f37 Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Wed, 11 Sep 2013 14:03:26 -0400
Subject: [PATCH 069/248] Removed private scope

Change-Id: Ia723321a5cb05deb626d34c7d8d78194e049b1f0
---
 app/models/user.rb       | 2 --
 lib/gitlab/oauth/user.rb | 2 +-
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/app/models/user.rb b/app/models/user.rb
index e92f0847724..ea1b9419288 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -383,8 +383,6 @@ class User < ActiveRecord::Base
     end
   end
 
-  private
-
   def with_defaults
     User.defaults.each do |k,v|
       self.send("#{k}=",v)
diff --git a/lib/gitlab/oauth/user.rb b/lib/gitlab/oauth/user.rb
index 515c5b769e5..1b32b99f4ba 100644
--- a/lib/gitlab/oauth/user.rb
+++ b/lib/gitlab/oauth/user.rb
@@ -27,7 +27,7 @@ module Gitlab
             password_confirmation: password,
           }
 
-          user = model.new(opts, as: :admin).with_defaults
+          user = model.build_user(opts, as: :admin)
           user.save!
           log.info "(OAuth) Creating user #{email} from login with extern_uid => #{uid}"
 
-- 
GitLab


From 9aab1b8b06132a80ad00b6ff95859bd99af07133 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 11 Sep 2013 22:20:51 +0300
Subject: [PATCH 070/248] New landing page when you have 0 projects

---
 app/assets/stylesheets/common.scss            |  9 ++++
 .../_zero_authorized_projects.html.haml       | 48 ++++++++++++++-----
 2 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss
index 66cc2ffc92d..6d80b22b3aa 100644
--- a/app/assets/stylesheets/common.scss
+++ b/app/assets/stylesheets/common.scss
@@ -373,3 +373,12 @@ table {
     text-align: center;
   }
 }
+
+.dashboard-intro-icon {
+  float: left;
+  font-size: 32px;
+  color: #AAA;
+  padding: 5px 0;
+  width: 50px;
+  min-height: 100px;
+}
diff --git a/app/views/dashboard/_zero_authorized_projects.html.haml b/app/views/dashboard/_zero_authorized_projects.html.haml
index ea5d8d6376f..79d5dca8845 100644
--- a/app/views/dashboard/_zero_authorized_projects.html.haml
+++ b/app/views/dashboard/_zero_authorized_projects.html.haml
@@ -1,12 +1,36 @@
-%h3.nothing_here_message
-  You don't have access to any projects.
-  %br
-  - if current_user.can_create_project?
-    You can create up to
-    = pluralize(current_user.projects_limit, "project") + "."
-    Click on the button below to add a new one
-    .link_holder
-      = link_to new_project_path, class: "btn btn-primary" do
-        New Project »
-  - else
-    If you are added to a project, it will be displayed here
+%h3.page-title Welcome to GitLab!
+%p.light Self Hosted Git Management application.
+%hr
+%div
+  .dashboard-intro-icon
+    %i.icon-bookmark-empty
+  %div
+    %p.slead
+      You don't have access to any projects right now.
+      %br
+      - if current_user.can_create_project?
+        You can create up to
+        %strong= pluralize(current_user.projects_limit, "project") + "."
+        Click on the button below to add a new one
+      - else
+        If you are added to a project, it will be displayed here
+
+    - if current_user.can_create_project?
+      .link_holder
+        = link_to new_project_path, class: "btn btn-new" do
+          New project »
+
+- if current_user.can_create_group?
+  %hr
+  %div
+    .dashboard-intro-icon
+      %i.icon-group
+    %div
+      %p.slead
+        You can create a group for several dependent projects.
+        %br
+        Group is the best way to manage projects and members
+      .link_holder
+        = link_to new_group_path, class: "btn btn-new" do
+          New group »
+
-- 
GitLab


From 524cc4f858571952c8c91793133ede2a392b0308 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 11 Sep 2013 22:46:37 +0300
Subject: [PATCH 071/248] Truncate some text from dashboard events

---
 app/helpers/application_helper.rb      | 7 +++++++
 app/helpers/events_helper.rb           | 4 +++-
 app/views/events/event/_push.html.haml | 2 +-
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 0a49892ca0a..4209b081bfa 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -235,4 +235,11 @@ module ApplicationHelper
       "Search"
     end
   end
+
+  def first_line(str)
+    lines = str.split("\n")
+    line = lines.first
+    line += "..." if lines.size > 1
+    line
+  end
 end
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index 3c637404c4f..cd8761a6113 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -123,6 +123,8 @@ module EventsHelper
   end
 
   def event_note(text)
-    sanitize(markdown(truncate(text, length: 150)), tags: %w(a img b pre p))
+    text = first_line(text)
+    text = truncate(text, length: 150)
+    sanitize(markdown(text), tags: %w(a img b pre p))
   end
 end
diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml
index f2b8dc4238c..adba9a5f619 100644
--- a/app/views/events/event/_push.html.haml
+++ b/app/views/events/event/_push.html.haml
@@ -5,7 +5,7 @@
     %strong= event.ref_name
   - else
     = link_to project_commits_path(event.project, event.ref_name) do
-      %strong= event.ref_name
+      %strong= truncate(event.ref_name, length: 30)
   at
   %strong= link_to_project event.project
 
-- 
GitLab


From 4204ce74667cf67280d2678611fb4ec8d963d558 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 11 Sep 2013 22:50:08 +0300
Subject: [PATCH 072/248] Remove commented tests since nobody is going to fix
 them

---
 .../project/forked_merge_requests.feature     |  9 ----
 features/project/issues/issues.feature        | 17 -------
 spec/features/notes_on_merge_requests_spec.rb | 45 -------------------
 3 files changed, 71 deletions(-)

diff --git a/features/project/forked_merge_requests.feature b/features/project/forked_merge_requests.feature
index 2c6c1ef574c..966905645a2 100644
--- a/features/project/forked_merge_requests.feature
+++ b/features/project/forked_merge_requests.feature
@@ -4,15 +4,6 @@ Feature: Project Forked Merge Requests
     And I am a member of project "Shop"
     And I have a project forked off of "Shop" called "Forked Shop"
 
-  # TODO: fix
-  #@javascript
-  #Scenario: I can visit the target projects commit for a forked merge request
-    #Given I visit project "Forked Shop" merge requests page
-    #And I click link "New Merge Request"
-    #And I fill out a "Merge Request On Forked Project" merge request
-    #And I follow the target commit link
-    #Then I should see the commit under the forked from project
-
   @javascript
   Scenario: I submit new unassigned merge request to a forked project
     Given I visit project "Forked Shop" merge requests page
diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature
index d6ef384c9a6..022188f8250 100644
--- a/features/project/issues/issues.feature
+++ b/features/project/issues/issues.feature
@@ -54,20 +54,3 @@ Feature: Project Issues
     And I fill in issue search with "0.3"
     Then I should see "Release 0.3" in issues
     And I should not see "Release 0.4" in issues
-
-  # Disable this two cause of random failing
-  # TODO: fix after v4.0 released
-  #@javascript
-  #Scenario: I create Issue with pre-selected milestone
-    #Given project "Shop" has milestone "v2.2"
-    #And project "Shop" has milestone "v3.0"
-    #And I visit project "Shop" issues page
-    #When I select milestone "v3.0"
-    #And I click link "New Issue"
-    #Then I should see selected milestone with title "v3.0"
-
-  #@javascript
-  #Scenario: I create Issue with pre-selected assignee
-    #When I select first assignee from "Shop" project
-    #And I click link "New Issue"
-    #Then I should see first assignee from "Shop" as selected assignee
diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb
index 16bdaf0f83c..ba580d9484d 100644
--- a/spec/features/notes_on_merge_requests_spec.rb
+++ b/spec/features/notes_on_merge_requests_spec.rb
@@ -206,17 +206,6 @@ describe "On a merge request diff", js: true, focus: true do
           find(".js-note-preview-button").trigger("click")
         end
       end
-
-      # TODO: fix
-      #it 'should check if previews were rendered separately' do
-      #within("tr[id='4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185'] + .js-temp-notes-holder") do
-      #should have_css(".js-note-preview", text: "One comment on line 185")
-      #end
-
-      #within("tr[id='342e16cbbd482ac2047dc679b2749d248cc1428f_18_17'] + .js-temp-notes-holder") do
-      #should have_css(".js-note-preview", text: "Another comment on line 17")
-      #end
-      #end
     end
 
     describe "posting a note" do
@@ -239,42 +228,8 @@ describe "On a merge request diff", js: true, focus: true do
         should have_css(".notes_holder .note", count: 1)
         should have_link("Reply")
       end
-
-      # TODO: fix
-      #it "should remove last note of a discussion" do
-      # within("tr[id='342e16cbbd482ac2047dc679b2749d248cc1428f_18_17'] + .notes-holder") do
-      #   find(".js-note-delete").click
-      # end
-      # should_not have_css(".note_holder")
-      #end
     end
   end
-
-  # TODO: fix
-  #describe "when replying to a note" do
-  #before do
-  ## create first note
-  # find('a[data-line-code="4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184"]').click
-
-  # within(".js-temp-notes-holder") do
-  # fill_in "note[note]", with: "One comment on line 184"
-  # click_button("Add Comment")
-  #end
-
-  # within(".js-temp-notes-holder") do
-  # find(".js-discussion-reply-button").click
-  # fill_in "note[note]", with: "An additional comment in reply"
-  # click_button("Add Comment")
-  # end
-  #end
-
-  #it 'should be inserted and form removed from reply' do
-  # should have_content("An additional comment in reply")
-  # within(".notes_holder") { should have_css(".note", count: 2) }
-  # within(".notes_holder") { should have_no_css("form") }
-  # within(".notes_holder") { should have_link("Reply") }
-  # end
-  #end
 end
 
 describe "On merge request discussion", js: true do
-- 
GitLab


From ab478f2a91160048a22da9e5e3c65bebac7c583c Mon Sep 17 00:00:00 2001
From: Ryan Mendivil <rsmendivil@gmail.com>
Date: Tue, 10 Sep 2013 17:36:04 -0800
Subject: [PATCH 073/248] Fix bug with rendering changing images in commits

When viewing the diff for a changed image file, two bugs occur:

- Both the 'before' and 'after' images link to the 'after' commit
- Visiting the link for either image will cause a error

The first is caused by both image links referencing '@commit.id' rather
than '@commit.parent_id'.  The second is caused by the use of
'project_tree_path' which is used for creating links to directories in
the git file tree. 'project_blob_path' which links to files should be
used instead.
---
 app/views/projects/commits/_image.html.haml      |  4 ++--
 features/project/commits/commits.feature         |  4 ++++
 features/steps/project/project_browse_commits.rb | 10 ++++++++++
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/app/views/projects/commits/_image.html.haml b/app/views/projects/commits/_image.html.haml
index db02fa333b9..73f87289d3d 100644
--- a/app/views/projects/commits/_image.html.haml
+++ b/app/views/projects/commits/_image.html.haml
@@ -9,7 +9,7 @@
     %div.two-up.view
       %span.wrap
         .frame.deleted
-          %a{href: project_tree_path(@project, tree_join(@commit.id, diff.old_path))}
+          %a{href: project_blob_path(@project, tree_join(@commit.parent_id, diff.old_path))}
             %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
         %p.image-info.hide
           %span.meta-filesize= "#{number_to_human_size old_file.size}"
@@ -21,7 +21,7 @@
           %span.meta-height
       %span.wrap
         .frame.added
-          %a{href: project_tree_path(@project, tree_join(@commit.id, diff.new_path))}
+          %a{href: project_blob_path(@project, tree_join(@commit.id, diff.new_path))}
             %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
         %p.image-info.hide
           %span.meta-filesize= "#{number_to_human_size file.size}"
diff --git a/features/project/commits/commits.feature b/features/project/commits/commits.feature
index d962471ebdb..fe470f5ac99 100644
--- a/features/project/commits/commits.feature
+++ b/features/project/commits/commits.feature
@@ -35,3 +35,7 @@ Feature: Project Browse commits
   Scenario: I browse huge commit
     Given I visit huge commit page
     Then I see huge commit message
+
+  Scenario: I browse a commit with an image
+    Given I visit a commit with an image that changed
+    Then The diff links to both the previous and current image
diff --git a/features/steps/project/project_browse_commits.rb b/features/steps/project/project_browse_commits.rb
index 4b122b853e6..650bc3a16f7 100644
--- a/features/steps/project/project_browse_commits.rb
+++ b/features/steps/project/project_browse_commits.rb
@@ -78,4 +78,14 @@ class ProjectBrowseCommits < Spinach::FeatureSteps
     page.should have_content "Warning! This is a large diff"
     page.should_not have_content "If you still want to see the diff"
   end
+
+  Given 'I visit a commit with an image that changed' do
+    visit project_commit_path(@project, 'cc1ba255d6c5ffdce87a357ba7ccc397a4f4026b')
+  end
+
+  Then 'The diff links to both the previous and current image' do
+    links = page.all('.two-up span div a')
+    links[0]['href'].should =~ %r{blob/bc3735004cb45cec5e0e4fa92710897a910a5957}
+    links[1]['href'].should =~ %r{blob/cc1ba255d6c5ffdce87a357ba7ccc397a4f4026b}
+  end
 end
-- 
GitLab


From 4bcc3d2021c4bcac9cdbd5809548b738c8232866 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Bornschein?= <jb@capsec.org>
Date: Thu, 12 Sep 2013 13:33:09 +0200
Subject: [PATCH 074/248] Minor UI change in
 iews/public/project/index.html.haml

Placeholder in search field was wrong
---
 app/views/public/projects/index.html.haml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/views/public/projects/index.html.haml b/app/views/public/projects/index.html.haml
index bfede94917a..7dbe560e7fc 100644
--- a/app/views/public/projects/index.html.haml
+++ b/app/views/public/projects/index.html.haml
@@ -8,7 +8,7 @@
       = form_tag public_projects_path, method: :get, class: 'form-inline' do |f|
         .search-holder
           .controls
-            = search_field_tag :search, params[:search], placeholder: "gitlab-ci", class: "span3 search-text-input", id: "projects_search"
+            = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "span3 search-text-input", id: "projects_search"
             = submit_tag 'Search', class: "btn btn-primary wide"
 
 .public-projects
-- 
GitLab


From 0187d18424bb5bbd32ac923ed2f32fd02a770277 Mon Sep 17 00:00:00 2001
From: Joerg Bornschein <jb@capsec.org>
Date: Thu, 12 Sep 2013 14:30:55 +0200
Subject: [PATCH 075/248] Fix typo in tests

---
 features/admin/users.feature        | 2 +-
 features/steps/admin/admin_users.rb | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/features/admin/users.feature b/features/admin/users.feature
index 4c951df9fe2..7f503cf9235 100644
--- a/features/admin/users.feature
+++ b/features/admin/users.feature
@@ -13,4 +13,4 @@ Feature: Admin Users
     And Input non ascii char in username
     And Click save
     Then See username error message
-    And Not chenged form action url
+    And Not changed form action url
diff --git a/features/steps/admin/admin_users.rb b/features/steps/admin/admin_users.rb
index 61b3ed91beb..33c1344eaeb 100644
--- a/features/steps/admin/admin_users.rb
+++ b/features/steps/admin/admin_users.rb
@@ -28,7 +28,7 @@ class AdminUsers < Spinach::FeatureSteps
     end
   end
 
-  And 'Not chenged form action url' do
+  And 'Not changed form action url' do
     page.should have_selector %(form[action="/admin/users/#{@user.username}"])
   end
 end
-- 
GitLab


From c54b40d16539e123242f6b88854883e58e053694 Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Thu, 12 Sep 2013 15:28:46 +0200
Subject: [PATCH 076/248] Rescue an error if group doesn't exist

---
 lib/tasks/gitlab/check.rake        | 6 ++++--
 lib/tasks/gitlab/task_helpers.rake | 6 +++++-
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 74b3e7787e6..1e9228a3509 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -479,11 +479,13 @@ namespace :gitlab do
         return
       end
 
-      if File.stat(repo_base_path).uid == uid_for(gitlab_shell_ssh_user) &&
-         File.stat(repo_base_path).gid == gid_for(gitlab_shell_owner_group)
+      uid = uid_for(gitlab_shell_ssh_user)
+      gid = gid_for(gitlab_shell_owner_group)
+      if File.stat(repo_base_path).uid == uid && File.stat(repo_base_path).gid == gid
         puts "yes".green
       else
         puts "no".red
+        puts "  User id for #{gitlab_shell_ssh_user}: #{uid}. Groupd id for #{gitlab_shell_owner_group}: #{gid}".blue
         try_fixing_it(
           "sudo chown -R #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group} #{repo_base_path}"
         )
diff --git a/lib/tasks/gitlab/task_helpers.rake b/lib/tasks/gitlab/task_helpers.rake
index f84257d15b5..ac2c4577c77 100644
--- a/lib/tasks/gitlab/task_helpers.rake
+++ b/lib/tasks/gitlab/task_helpers.rake
@@ -80,7 +80,11 @@ namespace :gitlab do
   end
 
   def gid_for(group_name)
-    Etc.getgrnam(group_name).gid
+    begin
+      Etc.getgrnam(group_name).gid
+    rescue ArgumentError # no group
+      "group #{group_name} doesn't exist"
+    end
   end
 
   def warn_user_is_not_gitlab
-- 
GitLab


From bda74563330627dbb199d65373745abb23106368 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 12 Sep 2013 18:59:31 +0300
Subject: [PATCH 077/248] Add UsersGroup observer

Trigger notification service when new user-group relation was created
---
 app/observers/users_group_observer.rb       |  9 +++++++
 spec/observers/users_group_observer_spec.rb | 27 +++++++++++++++++++++
 2 files changed, 36 insertions(+)
 create mode 100644 app/observers/users_group_observer.rb
 create mode 100644 spec/observers/users_group_observer_spec.rb

diff --git a/app/observers/users_group_observer.rb b/app/observers/users_group_observer.rb
new file mode 100644
index 00000000000..ecdbede89d9
--- /dev/null
+++ b/app/observers/users_group_observer.rb
@@ -0,0 +1,9 @@
+class UsersGroupObserver < BaseObserver
+  def after_create(membership)
+    notification.new_group_member(membership)
+  end
+
+  def after_update(membership)
+    notification.update_group_member(membership)
+  end
+end
diff --git a/spec/observers/users_group_observer_spec.rb b/spec/observers/users_group_observer_spec.rb
new file mode 100644
index 00000000000..3bf562edbb7
--- /dev/null
+++ b/spec/observers/users_group_observer_spec.rb
@@ -0,0 +1,27 @@
+require 'spec_helper'
+
+describe UsersGroupObserver do
+  before(:each) { enable_observers }
+  after(:each) { disable_observers }
+
+  subject { UsersGroupObserver.instance }
+  before { subject.stub(notification: mock('NotificationService').as_null_object) }
+
+  describe "#after_create" do
+    it "should send email to user" do
+      subject.should_receive(:notification)
+      create(:users_group)
+    end
+  end
+
+  describe "#after_update" do
+    before do
+      @membership = create :users_group
+    end
+
+    it "should send email to user" do
+      subject.should_receive(:notification)
+      @membership.update_attribute(:group_access, UsersGroup::MASTER)
+    end
+  end
+end
-- 
GitLab


From 474b606855b973e5f425016b2c67586b248e8f70 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 12 Sep 2013 19:00:32 +0300
Subject: [PATCH 078/248] Enable UsersGroup observer, Add group_member methods
 to NotificationService

---
 app/services/notification_service.rb |  8 ++++++++
 config/application.rb                |  1 +
 spec/mailers/notify_spec.rb          | 20 ++++++++++++++++++++
 3 files changed, 29 insertions(+)

diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index c20b07e69f0..71c25dc1b70 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -148,6 +148,14 @@ class NotificationService
     mailer.project_access_granted_email(users_project.id)
   end
 
+  def new_group_member(users_group)
+    mailer.group_access_granted_email(users_group.id)
+  end
+
+  def update_group_member(users_group)
+    mailer.group_access_granted_email(users_group.id)
+  end
+
   protected
 
   # Get project users with WATCH notification level
diff --git a/config/application.rb b/config/application.rb
index f7349fa009b..8ac07ef337a 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -32,6 +32,7 @@ module Gitlab
                                      :project_observer,
                                      :system_hook_observer,
                                      :user_observer,
+                                     :users_group_observer,
                                      :users_project_observer
 
     # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index 2f0475e5f02..0787bdbea6f 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -347,4 +347,24 @@ describe Notify do
       end
     end
   end
+
+  describe 'group access changed' do
+    let(:group) { create(:group) }
+    let(:user) { create(:user) }
+    let(:membership) { create(:users_group, group: group, user: user) }
+
+    subject { Notify.group_access_granted_email(membership.id) }
+
+    it 'has the correct subject' do
+      should have_subject /access to group was granted/
+    end
+
+    it 'contains name of project' do
+      should have_body_text /#{group.name}/
+    end
+
+    it 'contains new user role' do
+      should have_body_text /#{membership.human_access}/
+    end
+  end
 end
-- 
GitLab


From a04dbd262187473dfd8664fb8ffd23f0e5364084 Mon Sep 17 00:00:00 2001
From: Trung Ngo <ndtrung4419@gmail.com>
Date: Thu, 12 Sep 2013 23:20:55 +0700
Subject: [PATCH 079/248] Fix typo in installation.md

SSH is pronounced as /es es aged/, so we need "an" instead of "a".
---
 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 1f6b246b884..69130a06e0c 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -111,7 +111,7 @@ Create a `git` user for Gitlab:
 
 # 4. GitLab shell
 
-GitLab Shell is a ssh access and repository management software developed specially for GitLab.
+GitLab Shell is an ssh access and repository management software developed specially for GitLab.
 
     # Go to home directory
     cd /home/git
-- 
GitLab


From 8fa77ebf8d59aacc7acf8d00f8266f18aa2c35b1 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 12 Sep 2013 20:15:10 +0300
Subject: [PATCH 080/248] Compare page improved

* Show new merge request button from compare page
* Show message if user selected same branches
* Show message if compared branches are the same
* Prepend inputs with from/to labels
---
 .../stylesheets/gitlab_bootstrap/forms.scss   |  7 ++-
 app/helpers/compare_helper.rb                 | 12 +++++
 app/views/projects/compare/_form.html.haml    | 45 ++++++++-----------
 app/views/projects/compare/index.html.haml    | 10 +++++
 app/views/projects/compare/show.html.haml     | 13 ++++++
 app/views/projects/issues/_form.html.haml     |  4 +-
 6 files changed, 58 insertions(+), 33 deletions(-)
 create mode 100644 app/helpers/compare_helper.rb

diff --git a/app/assets/stylesheets/gitlab_bootstrap/forms.scss b/app/assets/stylesheets/gitlab_bootstrap/forms.scss
index 020a0bf7fd5..a2612166c78 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/forms.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/forms.scss
@@ -6,10 +6,9 @@ form {
   }
 }
 
-input {
-  &.input-xpadding {
-    padding: 6px 10px;
-  }
+input.input-xpadding,
+.add-on.input-xpadding {
+  padding: 6px 10px;
 }
 
 .control-group {
diff --git a/app/helpers/compare_helper.rb b/app/helpers/compare_helper.rb
new file mode 100644
index 00000000000..55d0d6268ad
--- /dev/null
+++ b/app/helpers/compare_helper.rb
@@ -0,0 +1,12 @@
+module CompareHelper
+  def compare_to_mr_button?
+    params[:from].present? && params[:to].present? &&
+      @repository.branch_names.include?(params[:from]) &&
+      @repository.branch_names.include?(params[:to]) &&
+      !@refs_are_same
+  end
+
+  def compare_mr_path
+    new_project_merge_request_path(@project, merge_request: {source_branch: params[:from], target_branch: params[:to]})
+  end
+end
diff --git a/app/views/projects/compare/_form.html.haml b/app/views/projects/compare/_form.html.haml
index 503b39c0663..ca1ea4073e6 100644
--- a/app/views/projects/compare/_form.html.haml
+++ b/app/views/projects/compare/_form.html.haml
@@ -1,30 +1,21 @@
-%div
-  - unless params[:to]
-    %p.slead
-      Fill input field with commit id like
-      %code.label-branch 4eedf23
-      or branch/tag name like
-      %code.label-branch master
-      and press compare button for the commits list and a code diff.
-      %br
-      Changes are shown <b>from</b> the version in the first field <b>to</b> the version in the second field.
-
-
-  = form_tag project_compare_index_path(@project), method: :post do
-    .clearfix
-      .pull-left
-        - if params[:to] && params[:from]
-          = link_to 'switch', {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has_tooltip', title: 'Switch base of comparison'}
-        = text_field_tag :from, params[:from], placeholder: "from", class: "input-xlarge input-xpadding"
-        = "..."
-        = text_field_tag :to, params[:to], placeholder: "to", class: "input-xlarge input-xpadding"
-      .pull-left
-        &nbsp;
-        = submit_tag "Compare", class: "btn btn-create commits-compare-btn"
-    - if @refs_are_same
-      .alert
-        %span Refs are the same
-
+= form_tag project_compare_index_path(@project), method: :post do
+  .clearfix
+    .pull-left
+      - if params[:to] && params[:from]
+        = link_to 'switch', {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has_tooltip', title: 'Switch base of comparison'}
+      .input-prepend
+        %span.add-on.input-xpadding from
+        = text_field_tag :from, params[:from], class: "span3 input-xpadding"
+      = "..."
+      .input-prepend
+        %span.add-on.input-xpadding to
+        = text_field_tag :to, params[:to], class: "span3 input-xpadding"
+    .pull-left
+      &nbsp;
+      = submit_tag "Compare", class: "btn btn-create commits-compare-btn"
+      - if compare_to_mr_button?
+        = link_to compare_mr_path, class: 'prepend-left-10' do
+          %strong Make a merge request
 
 
 :javascript
diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml
index 8f108ed0b08..4745bfbeaaf 100644
--- a/app/views/projects/compare/index.html.haml
+++ b/app/views/projects/compare/index.html.haml
@@ -2,5 +2,15 @@
 
 %h3.page-title
   Compare View
+%p.slead
+  Compare branches, tags or commit ranges.
+  %br
+  Fill input field with commit id like
+  %code.label-branch 4eedf23
+  or branch/tag name like
+  %code.label-branch master
+  and press compare button for the commits list and a code diff.
+  %br
+  Changes are shown <b>from</b> the version in the first field <b>to</b> the version in the second field.
 
 = render "form"
diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml
index af9273f9315..4be62d36917 100644
--- a/app/views/projects/compare/show.html.haml
+++ b/app/views/projects/compare/show.html.haml
@@ -20,3 +20,16 @@
   - unless @diffs.empty?
     %h4 Diff
     = render "projects/commits/diffs", diffs: @diffs, project: @project
+- else
+  .light-well
+    %center
+      %h4
+        There isn't anything to compare.
+      %p.slead
+        - if params[:to] == params[:from]
+          You'll need to use different branch names to get a valid comparison.
+        - else
+          %span.label-branch #{params[:from]}
+          and
+          %span.label-branch #{params[:to]}
+          are the same.
diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml
index 957cc5a7e2d..6acad9134d1 100644
--- a/app/views/projects/issues/_form.html.haml
+++ b/app/views/projects/issues/_form.html.haml
@@ -67,8 +67,8 @@
         event.preventDefault();
       }
     })
-    .bind( "click", function( event ) {
-        $( this ).autocomplete("search", "");
+    .bind("click", function(event) {
+      $(this).autocomplete("search", "");
     })
     .autocomplete({
       minLength: 0,
-- 
GitLab


From a7d83edbbf0f130c2ede375b5d9c23f21275ba7d Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 12 Sep 2013 20:23:03 +0300
Subject: [PATCH 081/248] Right branches for mr link at Compare view

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

diff --git a/app/helpers/compare_helper.rb b/app/helpers/compare_helper.rb
index 55d0d6268ad..e1dd89dcd3d 100644
--- a/app/helpers/compare_helper.rb
+++ b/app/helpers/compare_helper.rb
@@ -7,6 +7,6 @@ module CompareHelper
   end
 
   def compare_mr_path
-    new_project_merge_request_path(@project, merge_request: {source_branch: params[:from], target_branch: params[:to]})
+    new_project_merge_request_path(@project, merge_request: {source_branch: params[:to], target_branch: params[:from]})
   end
 end
-- 
GitLab


From bf922d0a07ee1d861a885de35d1e6c826e6e8674 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 12 Sep 2013 21:39:27 +0300
Subject: [PATCH 082/248] Compare link for branches

---
 app/helpers/compare_helper.rb                 | 1 +
 app/views/projects/branches/_branch.html.haml | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/app/helpers/compare_helper.rb b/app/helpers/compare_helper.rb
index e1dd89dcd3d..ea2540bf385 100644
--- a/app/helpers/compare_helper.rb
+++ b/app/helpers/compare_helper.rb
@@ -3,6 +3,7 @@ module CompareHelper
     params[:from].present? && params[:to].present? &&
       @repository.branch_names.include?(params[:from]) &&
       @repository.branch_names.include?(params[:to]) &&
+      params[:from] != params[:to] &&
       !@refs_are_same
   end
 
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index 026948aa027..b8392525791 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -13,6 +13,10 @@
         = link_to archive_project_repository_path(@project, ref: branch.name), class: 'btn grouped btn-small' do
           %i.icon-download-alt
           Download
+      = link_to project_compare_index_path(@project, from: branch.name, to: branch.name), class: 'btn grouped btn-small', title: "Compare" do
+        %i.icon-copy
+        Compare
+
       - if can?(current_user, :admin_project, @project) && branch.name != @repository.root_ref
         = link_to project_branch_path(@project, branch.name), class: 'btn grouped btn-small remove-row', method: :delete, confirm: 'Removed branch cannot be restored. Are you sure?', remote: true do
           %i.icon-trash
-- 
GitLab


From d9fb4a969173377655dd63df32a55c224fffbab6 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 12 Sep 2013 21:46:31 +0300
Subject: [PATCH 083/248] Add default values to compare page link

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

diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml
index c16abac7f17..624604142b1 100644
--- a/app/views/projects/commits/_head.html.haml
+++ b/app/views/projects/commits/_head.html.haml
@@ -4,7 +4,7 @@
   = nav_link(controller: [:commit, :commits]) do
     = link_to 'Commits', project_commits_path(@project, @repository.root_ref)
   = nav_link(controller: :compare) do
-    = link_to 'Compare', project_compare_index_path(@project)
+    = link_to 'Compare', project_compare_index_path(@project, from: @repository.root_ref, to: @ref || @repository.root_ref)
 
   = nav_link(html_options: {class: branches_tab_class}) do
     = link_to recent_project_branches_path(@project) do
-- 
GitLab


From b70ca8e3eb1588394f65e449cc27a861da28a7bd Mon Sep 17 00:00:00 2001
From: Hiroyuki Sato <sathiroyuki@gmail.com>
Date: Thu, 5 Sep 2013 20:46:34 +0900
Subject: [PATCH 084/248] Drop support of root namespace in routing

---
 config/routes.rb                              |  24 ++--
 features/steps/dashboard/dashboard.rb         |   2 +-
 features/steps/group/group.rb                 |   2 +-
 .../steps/project/project_network_graph.rb    |   5 -
 lib/api/merge_requests.rb                     |   2 +-
 spec/controllers/blob_controller_spec.rb      |   2 +-
 spec/controllers/commit_controller_spec.rb    |  14 +-
 spec/controllers/commits_controller_spec.rb   |   2 +-
 .../merge_requests_controller_spec.rb         |  14 +-
 spec/controllers/tree_controller_spec.rb      |   2 +-
 spec/factories.rb                             |   1 +
 spec/features/atom/issues_spec.rb             |   2 +-
 spec/models/project_spec.rb                   |  21 +--
 spec/requests/api/merge_requests_spec.rb      |  57 ++++----
 spec/routing/project_routing_spec.rb          | 122 +++++++++---------
 spec/routing/routing_spec.rb                  |   4 +-
 spec/services/git_push_service_spec.rb        |   2 +-
 17 files changed, 129 insertions(+), 149 deletions(-)

diff --git a/config/routes.rb b/config/routes.rb
index d0e29a5ab96..2b444c2a296 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -157,7 +157,7 @@ Gitlab::Application.routes.draw do
   #
   # Project Area
   #
-  resources :projects, constraints: { id: /(?:[a-zA-Z.0-9_\-]+\/)?[a-zA-Z.0-9_\-]+/ }, except: [:new, :create, :index], path: "/" do
+  resources :projects, constraints: { id: /[a-zA-Z.0-9_\-]+\/[a-zA-Z.0-9_\-]+/ }, except: [:new, :create, :index], path: "/" do
     member do
       put :transfer
       post :fork
@@ -177,13 +177,13 @@ Gitlab::Application.routes.draw do
       resources :graphs, only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/}
       match "/compare/:from...:to" => "compare#show", as: "compare", via: [:get, :post], constraints: {from: /.+/, to: /.+/}
 
-        resources :snippets do
+        resources :snippets, constraints: {id: /\d+/} do
           member do
             get "raw"
           end
         end
 
-      resources :wikis, only: [:show, :edit, :destroy, :create] do
+      resources :wikis, only: [:show, :edit, :destroy, :create], constraints: {id: /[a-zA-Z.0-9_\-]+/} do
         collection do
           get :pages
           put ':id' => 'wikis#update'
@@ -195,7 +195,7 @@ Gitlab::Application.routes.draw do
         end
       end
 
-      resource :wall, only: [:show] do
+      resource :wall, only: [:show], constraints: {id: /\d+/} do
         member do
           get 'notes'
         end
@@ -214,21 +214,21 @@ Gitlab::Application.routes.draw do
         end
       end
 
-      resources :deploy_keys do
+      resources :deploy_keys, constraints: {id: /\d+/} do
         member do
           put :enable
           put :disable
         end
       end
 
-      resources :branches, only: [:index, :new, :create, :destroy] do
+      resources :branches, only: [:index, :new, :create, :destroy], constraints: { id: /[a-zA-Z.\/0-9_\-#%+]+/ } do
         collection do
           get :recent
         end
       end
 
-      resources :tags, only: [:index, :new, :create, :destroy]
-      resources :protected_branches, only: [:index, :create, :destroy]
+      resources :tags, only: [:index, :new, :create, :destroy], constraints: { id: /[a-zA-Z.\/0-9_\-#%+]+/ }
+      resources :protected_branches, only: [:index, :create, :destroy], constraints: { id: /[a-zA-Z.\/0-9_\-#%+]+/ }
 
       resources :refs, only: [] do
         collection do
@@ -262,14 +262,14 @@ Gitlab::Application.routes.draw do
         end
       end
 
-      resources :hooks, only: [:index, :create, :destroy] do
+      resources :hooks, only: [:index, :create, :destroy], constraints: {id: /\d+/} do
         member do
           get :test
         end
       end
 
       resources :team, controller: 'team_members', only: [:index]
-      resources :milestones, except: [:destroy]
+      resources :milestones, except: [:destroy], constraints: {id: /\d+/}
 
       resources :labels, only: [:index] do
         collection do
@@ -283,7 +283,7 @@ Gitlab::Application.routes.draw do
         end
       end
 
-      resources :team_members, except: [:index, :edit] do
+      resources :team_members, except: [:index, :edit], constraints: { id: /[a-zA-Z.\/0-9_\-#%+]+/ } do
         collection do
 
           # Used for import team
@@ -293,7 +293,7 @@ Gitlab::Application.routes.draw do
         end
       end
 
-      resources :notes, only: [:index, :create, :destroy, :update] do
+      resources :notes, only: [:index, :create, :destroy, :update], constraints: {id: /\d+/} do
         member do
           delete :delete_attachment
         end
diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb
index 5baf4e757ac..bde32128b92 100644
--- a/features/steps/dashboard/dashboard.rb
+++ b/features/steps/dashboard/dashboard.rb
@@ -57,7 +57,7 @@ class Dashboard < Spinach::FeatureSteps
 
   And 'I have group with projects' do
     @group   = create(:group)
-    @project = create(:project, group: @group)
+    @project = create(:project, namespace: @group)
     @event   = create(:closed_issue_event, project: @project)
 
     @project.team << [current_user, :master]
diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb
index 45dda6ff55e..71f29121179 100644
--- a/features/steps/group/group.rb
+++ b/features/steps/group/group.rb
@@ -11,7 +11,7 @@ class Groups < Spinach::FeatureSteps
 
   And 'I have group with projects' do
     @group   = create(:group, owner: current_user)
-    @project = create(:project, group: @group)
+    @project = create(:project, namespace: @group)
     @event   = create(:closed_issue_event, project: @project)
 
     @project.team << [current_user, :master]
diff --git a/features/steps/project/project_network_graph.rb b/features/steps/project/project_network_graph.rb
index 57015f76626..127adecf7ed 100644
--- a/features/steps/project/project_network_graph.rb
+++ b/features/steps/project/project_network_graph.rb
@@ -38,11 +38,6 @@ class ProjectNetworkGraph < Spinach::FeatureSteps
     sleep 2
   end
 
-  When 'I switch ref to "v2.1.0"' do
-    page.select 'v2.1.0', from: 'ref'
-    sleep 2
-  end
-
   When 'click "Show only selected branch" checkbox' do
     find('#filter_ref').click
     sleep 2
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index d690f1d07e7..4a521c3daeb 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -4,7 +4,7 @@ module API
     before { authenticate! }
     before { Thread.current[:current_user] = current_user }
 
-    resource :projects do
+    resource :projects, requirements: { id: /[a-zA-Z.0-9_\-]+\/[a-zA-Z.0-9_\-]+/ } do
       helpers do
         def handle_merge_request_errors!(errors)
           if errors[:project_access].any?
diff --git a/spec/controllers/blob_controller_spec.rb b/spec/controllers/blob_controller_spec.rb
index 05d16f35545..479d8fc1a1d 100644
--- a/spec/controllers/blob_controller_spec.rb
+++ b/spec/controllers/blob_controller_spec.rb
@@ -17,7 +17,7 @@ describe Projects::BlobController do
   describe "GET show" do
     render_views
 
-    before { get :show, project_id: project.code, id: id }
+    before { get :show, project_id: project.to_param, id: id }
 
     context "valid branch, valid file" do
       let(:id) { 'master/README.md' }
diff --git a/spec/controllers/commit_controller_spec.rb b/spec/controllers/commit_controller_spec.rb
index 893d0fe089a..fdf0884f4e2 100644
--- a/spec/controllers/commit_controller_spec.rb
+++ b/spec/controllers/commit_controller_spec.rb
@@ -13,7 +13,7 @@ describe Projects::CommitController do
   describe "#show" do
     shared_examples "export as" do |format|
       it "should generally work" do
-        get :show, project_id: project.code, id: commit.id, format: format
+        get :show, project_id: project.to_param, id: commit.id, format: format
 
         expect(response).to be_success
       end
@@ -21,11 +21,11 @@ describe Projects::CommitController do
       it "should generate it" do
         Commit.any_instance.should_receive(:"to_#{format}")
 
-        get :show, project_id: project.code, id: commit.id, format: format
+        get :show, project_id: project.to_param, id: commit.id, format: format
       end
 
       it "should render it" do
-        get :show, project_id: project.code, id: commit.id, format: format
+        get :show, project_id: project.to_param, id: commit.id, format: format
 
         expect(response.body).to eq(commit.send(:"to_#{format}"))
       end
@@ -33,7 +33,7 @@ describe Projects::CommitController do
       it "should not escape Html" do
         Commit.any_instance.stub(:"to_#{format}").and_return('HTML entities &<>" ')
 
-        get :show, project_id: project.code, id: commit.id, format: format
+        get :show, project_id: project.to_param, id: commit.id, format: format
 
         expect(response.body).to_not include('&amp;')
         expect(response.body).to_not include('&gt;')
@@ -47,7 +47,7 @@ describe Projects::CommitController do
       let(:format) { :diff }
 
       it "should really only be a git diff" do
-        get :show, project_id: project.code, id: commit.id, format: format
+        get :show, project_id: project.to_param, id: commit.id, format: format
 
         expect(response.body).to start_with("diff --git")
       end
@@ -58,13 +58,13 @@ describe Projects::CommitController do
       let(:format) { :patch }
 
       it "should really be a git email patch" do
-        get :show, project_id: project.code, id: commit.id, format: format
+        get :show, project_id: project.to_param, id: commit.id, format: format
 
         expect(response.body).to start_with("From #{commit.id}")
       end
 
       it "should contain a git diff" do
-        get :show, project_id: project.code, id: commit.id, format: format
+        get :show, project_id: project.to_param, id: commit.id, format: format
 
         expect(response.body).to match(/^diff --git/)
       end
diff --git a/spec/controllers/commits_controller_spec.rb b/spec/controllers/commits_controller_spec.rb
index facae17a0ad..8263afc97a2 100644
--- a/spec/controllers/commits_controller_spec.rb
+++ b/spec/controllers/commits_controller_spec.rb
@@ -13,7 +13,7 @@ describe Projects::CommitsController do
   describe "GET show" do
     context "as atom feed" do
       it "should render as atom" do
-        get :show, project_id: project.path, id: "master", format: "atom"
+        get :show, project_id: project.to_param, id: "master", format: "atom"
         response.should be_success
         response.content_type.should == 'application/atom+xml'
       end
diff --git a/spec/controllers/merge_requests_controller_spec.rb b/spec/controllers/merge_requests_controller_spec.rb
index 3c1a9cb7268..69708edd8b1 100644
--- a/spec/controllers/merge_requests_controller_spec.rb
+++ b/spec/controllers/merge_requests_controller_spec.rb
@@ -14,7 +14,7 @@ describe Projects::MergeRequestsController do
   describe "#show" do
     shared_examples "export merge as" do |format|
       it "should generally work" do
-        get :show, project_id: project.code, id: merge_request.iid, format: format
+        get :show, project_id: project.to_param, id: merge_request.iid, format: format
 
         expect(response).to be_success
       end
@@ -22,11 +22,11 @@ describe Projects::MergeRequestsController do
       it "should generate it" do
         MergeRequest.any_instance.should_receive(:"to_#{format}")
 
-        get :show, project_id: project.code, id: merge_request.iid, format: format
+        get :show, project_id: project.to_param, id: merge_request.iid, format: format
       end
 
       it "should render it" do
-        get :show, project_id: project.code, id: merge_request.iid, format: format
+        get :show, project_id: project.to_param, id: merge_request.iid, format: format
 
         expect(response.body).to eq((merge_request.send(:"to_#{format}",user)).to_s)
       end
@@ -34,7 +34,7 @@ describe Projects::MergeRequestsController do
       it "should not escape Html" do
         MergeRequest.any_instance.stub(:"to_#{format}").and_return('HTML entities &<>" ')
 
-        get :show, project_id: project.code, id: merge_request.iid, format: format
+        get :show, project_id: project.to_param, id: merge_request.iid, format: format
 
         expect(response.body).to_not include('&amp;')
         expect(response.body).to_not include('&gt;')
@@ -48,7 +48,7 @@ describe Projects::MergeRequestsController do
       let(:format) { :diff }
 
       it "should really only be a git diff" do
-        get :show, project_id: project.code, id: merge_request.iid, format: format
+        get :show, project_id: project.to_param, id: merge_request.iid, format: format
 
         expect(response.body).to start_with("diff --git")
       end
@@ -59,13 +59,13 @@ describe Projects::MergeRequestsController do
       let(:format) { :patch }
 
       it "should really be a git email patch with commit" do
-        get :show, project_id: project.code, id: merge_request.iid, format: format
+        get :show, project_id: project.to_param, id: merge_request.iid, format: format
 
         expect(response.body[0..100]).to start_with("From #{merge_request.commits.last.id}")
       end
 
       it "should contain git diffs" do
-        get :show, project_id: project.code, id: merge_request.iid, format: format
+        get :show, project_id: project.to_param, id: merge_request.iid, format: format
 
         expect(response.body).to match(/^diff --git/)
       end
diff --git a/spec/controllers/tree_controller_spec.rb b/spec/controllers/tree_controller_spec.rb
index 3e41b406c4f..bb1232e6264 100644
--- a/spec/controllers/tree_controller_spec.rb
+++ b/spec/controllers/tree_controller_spec.rb
@@ -18,7 +18,7 @@ describe Projects::TreeController do
     # Make sure any errors accessing the tree in our views bubble up to this spec
     render_views
 
-    before { get :show, project_id: project.code, id: id }
+    before { get :show, project_id: project.to_param, id: id }
 
     context "valid branch, no path" do
       let(:id) { 'master' }
diff --git a/spec/factories.rb b/spec/factories.rb
index e657321c294..4c5e687ac3e 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -28,6 +28,7 @@ FactoryGirl.define do
   factory :project do
     sequence(:name) { |n| "project#{n}" }
     path { name.downcase.gsub(/\s/, '_') }
+    namespace
     creator
 
     trait :source do
diff --git a/spec/features/atom/issues_spec.rb b/spec/features/atom/issues_spec.rb
index 0488c1f2266..c9bbdad380f 100644
--- a/spec/features/atom/issues_spec.rb
+++ b/spec/features/atom/issues_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
 describe "Issues Feed" do
   describe "GET /issues" do
     let!(:user)     { create(:user) }
-    let!(:project)  { create(:project, namespace: user.namespace) }
+    let!(:project)  { create(:project) }
     let!(:issue)    { create(:issue, author: user, project: project) }
 
     before { project.team << [user, :developer] }
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 172adb5fc7a..3bac142f4e2 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -58,11 +58,11 @@ describe Project do
     let!(:project) { create(:project) }
 
     it { should validate_presence_of(:name) }
-    it { should validate_uniqueness_of(:name) }
+    it { should validate_uniqueness_of(:name).scoped_to(:namespace_id) }
     it { should ensure_length_of(:name).is_within(0..255) }
 
     it { should validate_presence_of(:path) }
-    it { should validate_uniqueness_of(:path) }
+    it { should validate_uniqueness_of(:path).scoped_to(:namespace_id) }
     it { should ensure_length_of(:path).is_within(0..255) }
     it { should ensure_length_of(:description).is_within(0..2000) }
     it { should validate_presence_of(:creator) }
@@ -157,15 +157,6 @@ describe Project do
       it { Project.find_with_namespace('gitlab/gitlab-ci').should == @project }
       it { Project.find_with_namespace('gitlab-ci').should be_nil }
     end
-
-    context 'w/o namespace' do
-      before do
-        @project = create(:project, name: 'gitlab-ci')
-      end
-
-      it { Project.find_with_namespace('gitlab-ci').should == @project }
-      it { Project.find_with_namespace('gitlab/gitlab-ci').should be_nil }
-    end
   end
 
   describe :to_param do
@@ -177,14 +168,6 @@ describe Project do
 
       it { @project.to_param.should == "gitlab/gitlab-ci" }
     end
-
-    context 'w/o namespace' do
-      before do
-        @project = create(:project, name: 'gitlab-ci')
-      end
-
-      it { @project.to_param.should == "gitlab-ci" }
-    end
   end
 
   describe :repository do
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 7b893c43379..fb4a7d9bc19 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -2,9 +2,10 @@ require "spec_helper"
 
 describe API::API do
   include ApiHelpers
-
+  before(:each) { ActiveRecord::Base.observers.enable(:user_observer) }
+  after(:each) { ActiveRecord::Base.observers.disable(:user_observer) }
   let(:user) { create(:user) }
-  let!(:project) {create(:project_with_code, creator_id: user.id) }
+  let!(:project) {create(:project_with_code, creator_id: user.id, namespace: user.namespace) }
   let!(:merge_request) { create(:merge_request, author: user, assignee: user, source_project: project, target_project: project, title: "Test") }
   before {
     project.team << [user, :reporters]
@@ -13,14 +14,14 @@ describe API::API do
   describe "GET /projects/:id/merge_requests" do
     context "when unauthenticated" do
       it "should return authentication error" do
-        get api("/projects/#{project.id}/merge_requests")
+        get api("/projects/#{project.to_param}/merge_requests")
         response.status.should == 401
       end
     end
 
     context "when authenticated" do
       it "should return an array of merge_requests" do
-        get api("/projects/#{project.id}/merge_requests", user)
+        get api("/projects/#{project.to_param}/merge_requests", user)
         response.status.should == 200
         json_response.should be_an Array
         json_response.first['title'].should == merge_request.title
@@ -30,13 +31,13 @@ describe API::API do
 
   describe "GET /projects/:id/merge_request/:merge_request_id" do
     it "should return merge_request" do
-      get api("/projects/#{project.id}/merge_request/#{merge_request.id}", user)
+      get api("/projects/#{project.to_param}/merge_request/#{merge_request.id}", user)
       response.status.should == 200
       json_response['title'].should == merge_request.title
     end
 
     it "should return a 404 error if merge_request_id not found" do
-      get api("/projects/#{project.id}/merge_request/999", user)
+      get api("/projects/#{project.to_param}/merge_request/999", user)
       response.status.should == 404
     end
   end
@@ -44,32 +45,32 @@ describe API::API do
   describe "POST /projects/:id/merge_requests" do
     context 'between branches projects' do
       it "should return merge_request" do
-        post api("/projects/#{project.id}/merge_requests", user),
+        post api("/projects/#{project.to_param}/merge_requests", user),
              title: 'Test merge_request', source_branch: "stable", target_branch: "master", author: user
         response.status.should == 201
         json_response['title'].should == 'Test merge_request'
       end
 
       it "should return 422 when source_branch equals target_branch" do
-        post api("/projects/#{project.id}/merge_requests", user),
+        post api("/projects/#{project.to_param}/merge_requests", user),
              title: "Test merge_request", source_branch: "master", target_branch: "master", author: user
         response.status.should == 422
       end
 
       it "should return 400 when source_branch is missing" do
-        post api("/projects/#{project.id}/merge_requests", user),
+        post api("/projects/#{project.to_param}/merge_requests", user),
              title: "Test merge_request", target_branch: "master", author: user
         response.status.should == 400
       end
 
       it "should return 400 when target_branch is missing" do
-        post api("/projects/#{project.id}/merge_requests", user),
+        post api("/projects/#{project.to_param}/merge_requests", user),
              title: "Test merge_request", source_branch: "stable", author: user
         response.status.should == 400
       end
 
       it "should return 400 when title is missing" do
-        post api("/projects/#{project.id}/merge_requests", user),
+        post api("/projects/#{project.to_param}/merge_requests", user),
              target_branch: 'master', source_branch: 'stable'
         response.status.should == 400
       end
@@ -89,54 +90,54 @@ describe API::API do
       end
 
       it "should return merge_request" do
-        post api("/projects/#{fork_project.id}/merge_requests", user2),
+        post api("/projects/#{fork_project.to_param}/merge_requests", user2),
              title: 'Test merge_request', source_branch: "stable", target_branch: "master", author: user2, target_project_id: project.id
         response.status.should == 201
         json_response['title'].should == 'Test merge_request'
       end
 
       it "should not return 422 when source_branch equals target_branch" do
-        project.id.should_not == fork_project.id
+        project.to_param.should_not == fork_project.to_param
         fork_project.forked?.should be_true
         fork_project.forked_from_project.should == project
-        post api("/projects/#{fork_project.id}/merge_requests", user2),
+        post api("/projects/#{fork_project.to_param}/merge_requests", user2),
              title: 'Test merge_request', source_branch: "master", target_branch: "master", author: user2, target_project_id: project.id
         response.status.should == 201
         json_response['title'].should == 'Test merge_request'
       end
 
       it "should return 400 when source_branch is missing" do
-        post api("/projects/#{fork_project.id}/merge_requests", user2),
+        post api("/projects/#{fork_project.to_param}/merge_requests", user2),
              title: 'Test merge_request', target_branch: "master", author: user2, target_project_id: project.id
         response.status.should == 400
       end
 
       it "should return 400 when target_branch is missing" do
-        post api("/projects/#{fork_project.id}/merge_requests", user2),
+        post api("/projects/#{fork_project.to_param}/merge_requests", user2),
              title: 'Test merge_request', target_branch: "master", author: user2, target_project_id: project.id
         response.status.should == 400
       end
 
       it "should return 400 when title is missing" do
-        post api("/projects/#{fork_project.id}/merge_requests", user2),
+        post api("/projects/#{fork_project.to_param}/merge_requests", user2),
              target_branch: 'master', source_branch: 'stable', author: user2, target_project_id: project.id
         response.status.should == 400
       end
 
       it "should return 400 when target_branch is specified and not a forked project" do
-        post api("/projects/#{project.id}/merge_requests", user),
+        post api("/projects/#{project.to_param}/merge_requests", user),
              title: 'Test merge_request', target_branch: 'master', source_branch: 'stable', author: user, target_project_id: fork_project.id
         response.status.should == 400
       end
 
       it "should return 400 when target_branch is specified and for a different fork" do
-        post api("/projects/#{fork_project.id}/merge_requests", user2),
+        post api("/projects/#{fork_project.to_param}/merge_requests", user2),
              title: 'Test merge_request', target_branch: 'master', source_branch: 'stable', author: user2, target_project_id: unrelated_project.id
         response.status.should == 400
       end
 
       it "should return 201 when target_branch is specified and for the same project" do
-        post api("/projects/#{fork_project.id}/merge_requests", user2),
+        post api("/projects/#{fork_project.to_param}/merge_requests", user2),
              title: 'Test merge_request', target_branch: 'master', source_branch: 'stable', author: user2, target_project_id: fork_project.id
         response.status.should == 201
       end
@@ -145,7 +146,7 @@ describe API::API do
 
   describe "PUT /projects/:id/merge_request/:merge_request_id to close MR" do
     it "should return merge_request" do
-      put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), state_event: "close"
+      put api("/projects/#{project.to_param}/merge_request/#{merge_request.id}", user), state_event: "close"
       response.status.should == 200
       json_response['state'].should == 'closed'
     end
@@ -153,7 +154,7 @@ describe API::API do
 
   describe "PUT /projects/:id/merge_request/:merge_request_id to merge MR" do
     it "should return merge_request" do
-      put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), state_event: "merge"
+      put api("/projects/#{project.to_param}/merge_request/#{merge_request.id}", user), state_event: "merge"
       response.status.should == 200
       json_response['state'].should == 'merged'
     end
@@ -161,19 +162,19 @@ describe API::API do
 
   describe "PUT /projects/:id/merge_request/:merge_request_id" do
     it "should return merge_request" do
-      put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), title: "New title"
+      put api("/projects/#{project.to_param}/merge_request/#{merge_request.id}", user), title: "New title"
       response.status.should == 200
       json_response['title'].should == 'New title'
     end
 
     it "should return 422 when source_branch and target_branch are renamed the same" do
-      put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user),
+      put api("/projects/#{project.to_param}/merge_request/#{merge_request.id}", user),
           source_branch: "master", target_branch: "master"
       response.status.should == 422
     end
 
     it "should return merge_request with renamed target_branch" do
-      put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), target_branch: "wiki"
+      put api("/projects/#{project.to_param}/merge_request/#{merge_request.id}", user), target_branch: "wiki"
       response.status.should == 200
       json_response['target_branch'].should == 'wiki'
     end
@@ -181,18 +182,18 @@ describe API::API do
 
   describe "POST /projects/:id/merge_request/:merge_request_id/comments" do
     it "should return comment" do
-      post api("/projects/#{project.id}/merge_request/#{merge_request.id}/comments", user), note: "My comment"
+      post api("/projects/#{project.to_param}/merge_request/#{merge_request.id}/comments", user), note: "My comment"
       response.status.should == 201
       json_response['note'].should == 'My comment'
     end
 
     it "should return 400 if note is missing" do
-      post api("/projects/#{project.id}/merge_request/#{merge_request.id}/comments", user)
+      post api("/projects/#{project.to_param}/merge_request/#{merge_request.id}/comments", user)
       response.status.should == 400
     end
 
     it "should return 404 if note is attached to non existent merge request" do
-      post api("/projects/#{project.id}/merge_request/111/comments", user), note: "My comment"
+      post api("/projects/#{project.to_param}/merge_request/111/comments", user), note: "My comment"
       response.status.should == 404
     end
   end
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index 5fb0f860c42..20c04e94c24 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -25,31 +25,31 @@ shared_examples "RESTful project resources" do
   let(:actions) { [:index, :create, :new, :edit, :show, :update, :destroy] }
 
   it "to #index" do
-    get("/gitlabhq/#{controller}").should route_to("projects/#{controller}#index", project_id: 'gitlabhq') if actions.include?(:index)
+    get("/gitlab/gitlabhq/#{controller}").should route_to("projects/#{controller}#index", project_id: 'gitlab/gitlabhq') if actions.include?(:index)
   end
 
   it "to #create" do
-    post("/gitlabhq/#{controller}").should route_to("projects/#{controller}#create", project_id: 'gitlabhq') if actions.include?(:create)
+    post("/gitlab/gitlabhq/#{controller}").should route_to("projects/#{controller}#create", project_id: 'gitlab/gitlabhq') if actions.include?(:create)
   end
 
   it "to #new" do
-    get("/gitlabhq/#{controller}/new").should route_to("projects/#{controller}#new", project_id: 'gitlabhq') if actions.include?(:new)
+    get("/gitlab/gitlabhq/#{controller}/new").should route_to("projects/#{controller}#new", project_id: 'gitlab/gitlabhq') if actions.include?(:new)
   end
 
   it "to #edit" do
-    get("/gitlabhq/#{controller}/1/edit").should route_to("projects/#{controller}#edit", project_id: 'gitlabhq', id: '1') if actions.include?(:edit)
+    get("/gitlab/gitlabhq/#{controller}/1/edit").should route_to("projects/#{controller}#edit", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:edit)
   end
 
   it "to #show" do
-    get("/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#show", project_id: 'gitlabhq', id: '1') if actions.include?(:show)
+    get("/gitlab/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#show", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:show)
   end
 
   it "to #update" do
-    put("/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#update", project_id: 'gitlabhq', id: '1') if actions.include?(:update)
+    put("/gitlab/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#update", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:update)
   end
 
   it "to #destroy" do
-    delete("/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#destroy", project_id: 'gitlabhq', id: '1') if actions.include?(:destroy)
+    delete("/gitlab/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#destroy", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:destroy)
   end
 end
 
@@ -72,31 +72,31 @@ describe ProjectsController, "routing" do
   end
 
   it "to #fork" do
-    post("/gitlabhq/fork").should route_to('projects#fork', id: 'gitlabhq')
+    post("/gitlab/gitlabhq/fork").should route_to('projects#fork', id: 'gitlab/gitlabhq')
   end
 
   it "to #wall" do
-    get("/gitlabhq/wall").should route_to('projects/walls#show', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/wall").should route_to('projects/walls#show', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #edit" do
-    get("/gitlabhq/edit").should route_to('projects#edit', id: 'gitlabhq')
+    get("/gitlab/gitlabhq/edit").should route_to('projects#edit', id: 'gitlab/gitlabhq')
   end
 
   it "to #autocomplete_sources" do
-    get('/gitlabhq/autocomplete_sources').should route_to('projects#autocomplete_sources', id: "gitlabhq")
+    get('/gitlab/gitlabhq/autocomplete_sources').should route_to('projects#autocomplete_sources', id: "gitlab/gitlabhq")
   end
 
   it "to #show" do
-    get("/gitlabhq").should route_to('projects#show', id: 'gitlabhq')
+    get("/gitlab/gitlabhq").should route_to('projects#show', id: 'gitlab/gitlabhq')
   end
 
   it "to #update" do
-    put("/gitlabhq").should route_to('projects#update', id: 'gitlabhq')
+    put("/gitlab/gitlabhq").should route_to('projects#update', id: 'gitlab/gitlabhq')
   end
 
   it "to #destroy" do
-    delete("/gitlabhq").should route_to('projects#destroy', id: 'gitlabhq')
+    delete("/gitlab/gitlabhq").should route_to('projects#destroy', id: 'gitlab/gitlabhq')
   end
 end
 
@@ -108,11 +108,11 @@ end
 #                      DELETE /:project_id/wikis/:id(.:format)         projects/wikis#destroy
 describe Projects::WikisController, "routing" do
   it "to #pages" do
-    get("/gitlabhq/wikis/pages").should route_to('projects/wikis#pages', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/wikis/pages").should route_to('projects/wikis#pages', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #history" do
-    get("/gitlabhq/wikis/1/history").should route_to('projects/wikis#history', project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/wikis/1/history").should route_to('projects/wikis#history', project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it_behaves_like "RESTful project resources" do
@@ -127,23 +127,23 @@ end
 #     edit_project_repository GET    /:project_id/repository/edit(.:format)     projects/repositories#edit
 describe Projects::RepositoriesController, "routing" do
   it "to #archive" do
-    get("/gitlabhq/repository/archive").should route_to('projects/repositories#archive', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/repository/archive").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #show" do
-    get("/gitlabhq/repository").should route_to('projects/repositories#show', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/repository").should route_to('projects/repositories#show', project_id: 'gitlab/gitlabhq')
   end
 end
 
 describe Projects::BranchesController, "routing" do
   it "to #branches" do
-    get("/gitlabhq/branches").should route_to('projects/branches#index', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/branches").should route_to('projects/branches#index', project_id: 'gitlab/gitlabhq')
   end
 end
 
 describe Projects::TagsController, "routing" do
   it "to #tags" do
-    get("/gitlabhq/tags").should route_to('projects/tags#index', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/tags").should route_to('projects/tags#index', project_id: 'gitlab/gitlabhq')
   end
 end
 
@@ -176,16 +176,16 @@ end
 #  logs_file_project_ref GET    /:project_id/refs/:id/logs_tree/:path(.:format) refs#logs_tree
 describe Projects::RefsController, "routing" do
   it "to #switch" do
-    get("/gitlabhq/refs/switch").should route_to('projects/refs#switch', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/refs/switch").should route_to('projects/refs#switch', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #logs_tree" do
-    get("/gitlabhq/refs/stable/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlabhq', id: 'stable')
-    get("/gitlabhq/refs/feature%2345/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlabhq', id: 'feature#45')
-    get("/gitlabhq/refs/feature%2B45/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlabhq', id: 'feature+45')
-    get("/gitlabhq/refs/stable/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz')
-    get("/gitlabhq/refs/feature%2345/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlabhq', id: 'feature#45', path: 'foo/bar/baz')
-    get("/gitlabhq/refs/feature%2B45/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlabhq', id: 'feature+45', path: 'foo/bar/baz')
+    get("/gitlab/gitlabhq/refs/stable/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable')
+    get("/gitlab/gitlabhq/refs/feature%2345/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature#45')
+    get("/gitlab/gitlabhq/refs/feature%2B45/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature+45')
+    get("/gitlab/gitlabhq/refs/stable/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable', path: 'foo/bar/baz')
+    get("/gitlab/gitlabhq/refs/feature%2345/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature#45', path: 'foo/bar/baz')
+    get("/gitlab/gitlabhq/refs/feature%2B45/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature+45', path: 'foo/bar/baz')
     get("/gitlab/gitlabhq/refs/stable/logs_tree/files.scss").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable', path: 'files.scss')
   end
 end
@@ -204,28 +204,28 @@ end
 #                                       DELETE /:project_id/merge_requests/:id(.:format)                 projects/merge_requests#destroy
 describe Projects::MergeRequestsController, "routing" do
   it "to #diffs" do
-    get("/gitlabhq/merge_requests/1/diffs").should route_to('projects/merge_requests#diffs', project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/merge_requests/1/diffs").should route_to('projects/merge_requests#diffs', project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it "to #automerge" do
-    get("/gitlabhq/merge_requests/1/automerge").should route_to('projects/merge_requests#automerge', project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/merge_requests/1/automerge").should route_to('projects/merge_requests#automerge', project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it "to #automerge_check" do
-    get("/gitlabhq/merge_requests/1/automerge_check").should route_to('projects/merge_requests#automerge_check', project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/merge_requests/1/automerge_check").should route_to('projects/merge_requests#automerge_check', project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it "to #branch_from" do
-    get("/gitlabhq/merge_requests/branch_from").should route_to('projects/merge_requests#branch_from', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/merge_requests/branch_from").should route_to('projects/merge_requests#branch_from', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #branch_to" do
-    get("/gitlabhq/merge_requests/branch_to").should route_to('projects/merge_requests#branch_to', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/merge_requests/branch_to").should route_to('projects/merge_requests#branch_to', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #show" do
-    get("/gitlabhq/merge_requests/1.diff").should route_to('projects/merge_requests#show', project_id: 'gitlabhq', id: '1', format: 'diff')
-    get("/gitlabhq/merge_requests/1.patch").should route_to('projects/merge_requests#show', project_id: 'gitlabhq', id: '1', format: 'patch')
+    get("/gitlab/gitlabhq/merge_requests/1.diff").should route_to('projects/merge_requests#show', project_id: 'gitlab/gitlabhq', id: '1', format: 'diff')
+    get("/gitlab/gitlabhq/merge_requests/1.patch").should route_to('projects/merge_requests#show', project_id: 'gitlab/gitlabhq', id: '1', format: 'patch')
   end
 
   it_behaves_like "RESTful project resources" do
@@ -244,35 +244,35 @@ end
 #                      DELETE /:project_id/snippets/:id(.:format)      snippets#destroy
 describe SnippetsController, "routing" do
   it "to #raw" do
-    get("/gitlabhq/snippets/1/raw").should route_to('projects/snippets#raw', project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/snippets/1/raw").should route_to('projects/snippets#raw', project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it "to #index" do
-    get("/gitlabhq/snippets").should route_to("projects/snippets#index", project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/snippets").should route_to("projects/snippets#index", project_id: 'gitlab/gitlabhq')
   end
 
   it "to #create" do
-    post("/gitlabhq/snippets").should route_to("projects/snippets#create", project_id: 'gitlabhq')
+    post("/gitlab/gitlabhq/snippets").should route_to("projects/snippets#create", project_id: 'gitlab/gitlabhq')
   end
 
   it "to #new" do
-    get("/gitlabhq/snippets/new").should route_to("projects/snippets#new", project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/snippets/new").should route_to("projects/snippets#new", project_id: 'gitlab/gitlabhq')
   end
 
   it "to #edit" do
-    get("/gitlabhq/snippets/1/edit").should route_to("projects/snippets#edit", project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/snippets/1/edit").should route_to("projects/snippets#edit", project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it "to #show" do
-    get("/gitlabhq/snippets/1").should route_to("projects/snippets#show", project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/snippets/1").should route_to("projects/snippets#show", project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it "to #update" do
-    put("/gitlabhq/snippets/1").should route_to("projects/snippets#update", project_id: 'gitlabhq', id: '1')
+    put("/gitlab/gitlabhq/snippets/1").should route_to("projects/snippets#update", project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it "to #destroy" do
-    delete("/gitlabhq/snippets/1").should route_to("projects/snippets#destroy", project_id: 'gitlabhq', id: '1')
+    delete("/gitlab/gitlabhq/snippets/1").should route_to("projects/snippets#destroy", project_id: 'gitlab/gitlabhq', id: '1')
   end
 end
 
@@ -282,7 +282,7 @@ end
 #      project_hook DELETE /:project_id/hooks/:id(.:format)      hooks#destroy
 describe Projects::HooksController, "routing" do
   it "to #test" do
-    get("/gitlabhq/hooks/1/test").should route_to('projects/hooks#test', project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/hooks/1/test").should route_to('projects/hooks#test', project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it_behaves_like "RESTful project resources" do
@@ -294,10 +294,10 @@ end
 # project_commit GET    /:project_id/commit/:id(.:format) commit#show {id: /[[:alnum:]]{6,40}/, project_id: /[^\/]+/}
 describe Projects::CommitController, "routing" do
   it "to #show" do
-    get("/gitlabhq/commit/4246fb").should route_to('projects/commit#show', project_id: 'gitlabhq', id: '4246fb')
-    get("/gitlabhq/commit/4246fb.diff").should route_to('projects/commit#show', project_id: 'gitlabhq', id: '4246fb', format: 'diff')
-    get("/gitlabhq/commit/4246fb.patch").should route_to('projects/commit#show', project_id: 'gitlabhq', id: '4246fb', format: 'patch')
-    get("/gitlabhq/commit/4246fbd13872934f72a8fd0d6fb1317b47b59cb5").should route_to('projects/commit#show', project_id: 'gitlabhq', id: '4246fbd13872934f72a8fd0d6fb1317b47b59cb5')
+    get("/gitlab/gitlabhq/commit/4246fb").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb')
+    get("/gitlab/gitlabhq/commit/4246fb.diff").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb', format: 'diff')
+    get("/gitlab/gitlabhq/commit/4246fb.patch").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb', format: 'patch')
+    get("/gitlab/gitlabhq/commit/4246fbd13872934f72a8fd0d6fb1317b47b59cb5").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fbd13872934f72a8fd0d6fb1317b47b59cb5')
   end
 end
 
@@ -347,7 +347,7 @@ end
 # project_labels GET    /:project_id/labels(.:format) labels#index
 describe Projects::LabelsController, "routing" do
   it "to #index" do
-    get("/gitlabhq/labels").should route_to('projects/labels#index', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/labels").should route_to('projects/labels#index', project_id: 'gitlab/gitlabhq')
   end
 end
 
@@ -363,7 +363,7 @@ end
 #                            DELETE /:project_id/issues/:id(.:format)         issues#destroy
 describe Projects::IssuesController, "routing" do
   it "to #bulk_update" do
-    post("/gitlabhq/issues/bulk_update").should route_to('projects/issues#bulk_update', project_id: 'gitlabhq')
+    post("/gitlab/gitlabhq/issues/bulk_update").should route_to('projects/issues#bulk_update', project_id: 'gitlab/gitlabhq')
   end
 
   it_behaves_like "RESTful project resources" do
@@ -378,7 +378,7 @@ end
 #          project_note DELETE /:project_id/notes/:id(.:format)     notes#destroy
 describe Projects::NotesController, "routing" do
   it "to #preview" do
-    post("/gitlabhq/notes/preview").should route_to('projects/notes#preview', project_id: 'gitlabhq')
+    post("/gitlab/gitlabhq/notes/preview").should route_to('projects/notes#preview', project_id: 'gitlab/gitlabhq')
   end
 
   it_behaves_like "RESTful project resources" do
@@ -390,7 +390,7 @@ end
 # project_blame GET    /:project_id/blame/:id(.:format) blame#show {id: /.+/, project_id: /[^\/]+/}
 describe Projects::BlameController, "routing" do
   it "to #show" do
-    get("/gitlabhq/blame/master/app/models/project.rb").should route_to('projects/blame#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
+    get("/gitlab/gitlabhq/blame/master/app/models/project.rb").should route_to('projects/blame#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb')
     get("/gitlab/gitlabhq/blame/master/files.scss").should route_to('projects/blame#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
   end
 end
@@ -398,8 +398,8 @@ end
 # project_blob GET    /:project_id/blob/:id(.:format) blob#show {id: /.+/, project_id: /[^\/]+/}
 describe Projects::BlobController, "routing" do
   it "to #show" do
-    get("/gitlabhq/blob/master/app/models/project.rb").should route_to('projects/blob#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
-    get("/gitlabhq/blob/master/app/models/compare.rb").should route_to('projects/blob#show', project_id: 'gitlabhq', id: 'master/app/models/compare.rb')
+    get("/gitlab/gitlabhq/blob/master/app/models/project.rb").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb')
+    get("/gitlab/gitlabhq/blob/master/app/models/compare.rb").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/compare.rb')
     get("/gitlab/gitlabhq/blob/master/files.scss").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
   end
 end
@@ -407,7 +407,7 @@ end
 # project_tree GET    /:project_id/tree/:id(.:format) tree#show {id: /.+/, project_id: /[^\/]+/}
 describe Projects::TreeController, "routing" do
   it "to #show" do
-    get("/gitlabhq/tree/master/app/models/project.rb").should route_to('projects/tree#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
+    get("/gitlab/gitlabhq/tree/master/app/models/project.rb").should route_to('projects/tree#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb')
     get("/gitlab/gitlabhq/tree/master/files.scss").should route_to('projects/tree#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
   end
 end
@@ -417,28 +417,28 @@ end
 #       project_compare        /:project_id/compare/:from...:to(.:format) compare#show {from: /.+/, to: /.+/, id: /[^\/]+/, project_id: /[^\/]+/}
 describe Projects::CompareController, "routing" do
   it "to #index" do
-    get("/gitlabhq/compare").should route_to('projects/compare#index', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/compare").should route_to('projects/compare#index', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #compare" do
-    post("/gitlabhq/compare").should route_to('projects/compare#create', project_id: 'gitlabhq')
+    post("/gitlab/gitlabhq/compare").should route_to('projects/compare#create', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #show" do
-    get("/gitlabhq/compare/master...stable").should     route_to('projects/compare#show', project_id: 'gitlabhq', from: 'master', to: 'stable')
-    get("/gitlabhq/compare/issue/1234...stable").should route_to('projects/compare#show', project_id: 'gitlabhq', from: 'issue/1234', to: 'stable')
+    get("/gitlab/gitlabhq/compare/master...stable").should     route_to('projects/compare#show', project_id: 'gitlab/gitlabhq', from: 'master', to: 'stable')
+    get("/gitlab/gitlabhq/compare/issue/1234...stable").should route_to('projects/compare#show', project_id: 'gitlab/gitlabhq', from: 'issue/1234', to: 'stable')
   end
 end
 
 describe Projects::NetworkController, "routing" do
   it "to #show" do
-    get("/gitlabhq/network/master").should route_to('projects/network#show', project_id: 'gitlabhq', id: 'master')
-    get("/gitlabhq/network/master.json").should route_to('projects/network#show', project_id: 'gitlabhq', id: 'master', format: "json")
+    get("/gitlab/gitlabhq/network/master").should route_to('projects/network#show', project_id: 'gitlab/gitlabhq', id: 'master')
+    get("/gitlab/gitlabhq/network/master.json").should route_to('projects/network#show', project_id: 'gitlab/gitlabhq', id: 'master', format: "json")
   end
 end
 
 describe Projects::GraphsController, "routing" do
   it "to #show" do
-    get("/gitlabhq/graphs/master").should route_to('projects/graphs#show', project_id: 'gitlabhq', id: 'master')
+    get("/gitlab/gitlabhq/graphs/master").should route_to('projects/graphs#show', project_id: 'gitlab/gitlabhq', id: 'master')
   end
 end
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index cc2a141c454..946ef7c28cb 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -11,11 +11,11 @@ end
 #            /:path       Grack
 describe "Mounted Apps", "routing" do
   it "to API" do
-    get("/api").should be_routable
+    get("/api/issues").should be_routable
   end
 
   it "to Grack" do
-    get("/gitlabhq.git").should be_routable
+    get("/gitlab/gitlabhq.git").should be_routable
   end
 end
 
diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb
index 1f6ee818a42..e3c25fa0469 100644
--- a/spec/services/git_push_service_spec.rb
+++ b/spec/services/git_push_service_spec.rb
@@ -48,7 +48,7 @@ describe GitPushService do
         it { should include(id: @commit.id) }
         it { should include(message: @commit.safe_message) }
         it { should include(timestamp: @commit.date.xmlschema) }
-        it { should include(url: "#{Gitlab.config.gitlab.url}/#{project.code}/commit/#{@commit.id}") }
+        it { should include(url: "#{Gitlab.config.gitlab.url}/#{project.to_param}/commit/#{@commit.id}") }
 
         context "with a author" do
           subject { @push_data[:commits].first[:author] }
-- 
GitLab


From fa966fb7f74706217e98a66486a8605a10150ee7 Mon Sep 17 00:00:00 2001
From: Hiroyuki Sato <sathiroyuki@gmail.com>
Date: Fri, 13 Sep 2013 07:30:49 +0900
Subject: [PATCH 085/248] Improve timing problem in spinach test

---
 features/support/env.rb | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/features/support/env.rb b/features/support/env.rb
index 61f8dc29670..8798e62ea72 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -26,10 +26,13 @@ WebMock.allow_net_connect!
 #
 require 'capybara/poltergeist'
 Capybara.javascript_driver = :poltergeist
+Capybara.register_driver :poltergeist do |app|
+    Capybara::Poltergeist::Driver.new(app, :js_errors => false, :timeout => 60)
+end
 Spinach.hooks.on_tag("javascript") do
   ::Capybara.current_driver = ::Capybara.javascript_driver
 end
-Capybara.default_wait_time = 10
+Capybara.default_wait_time = 60
 Capybara.ignore_hidden_elements = false
 
 DatabaseCleaner.strategy = :truncation
-- 
GitLab


From 3f6272084bb47cb1519021bab49e0d73a912593f Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Fri, 13 Sep 2013 07:44:30 +0200
Subject: [PATCH 086/248] Notice about moving projects.

---
 doc/update/5.4-to-6.0.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md
index 907a134ed1d..8ad318f44b7 100644
--- a/doc/update/5.4-to-6.0.md
+++ b/doc/update/5.4-to-6.0.md
@@ -4,8 +4,8 @@
 
 #### Global projects
 
-We deprecated root(global) namespace for projects.
-So you need to move all your global projects under group/users manually before update or they will be automatically moved to the owner namespace during the update.
+The root (global) namespace for projects is depreated.
+So you need to move all your global projects under groups or users manually before update or they will be automatically moved to the project owner namespace during the update. When a project is moved all its members will receive an email with instructions how to update their git remote url. Please make sure you disable ssending email when you do a test of the upgrade.
 
 #### Teams
 
-- 
GitLab


From d1cc35cc04dd38334ce9ad10b26dcc3759e71279 Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Fri, 13 Sep 2013 07:49:45 +0200
Subject: [PATCH 087/248] Typo fix.

---
 doc/update/5.4-to-6.0.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md
index 8ad318f44b7..3b1d9878204 100644
--- a/doc/update/5.4-to-6.0.md
+++ b/doc/update/5.4-to-6.0.md
@@ -4,7 +4,7 @@
 
 #### Global projects
 
-The root (global) namespace for projects is depreated.
+The root (global) namespace for projects is deprecated.
 So you need to move all your global projects under groups or users manually before update or they will be automatically moved to the project owner namespace during the update. When a project is moved all its members will receive an email with instructions how to update their git remote url. Please make sure you disable ssending email when you do a test of the upgrade.
 
 #### Teams
-- 
GitLab


From b3b7a4f1c9a71b7786bf828acb47998f987042b0 Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Fri, 13 Sep 2013 10:12:42 +0200
Subject: [PATCH 088/248] Replace remote url on selection.

---
 app/assets/javascripts/project.js.coffee | 1 +
 app/views/projects/empty.html.haml       | 6 ++++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee
index 780292daa11..83236b34814 100644
--- a/app/assets/javascripts/project.js.coffee
+++ b/app/assets/javascripts/project.js.coffee
@@ -35,6 +35,7 @@ $ ->
       $('a, button', scope).removeClass 'active'
       $(@).addClass 'active'
       $('#project_clone', scope).val $(@).data 'clone'
+      $(".clone").text("").append 'git remote add origin ' + $(@).data 'clone'
 
   # Ref switcher
   $('.project-refs-select').on 'change', ->
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 99e334cc6b8..001857cefda 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -29,7 +29,8 @@
           touch README
           git add README
           git commit -m 'first commit'
-          git remote add origin #{@project.url_to_repo}
+        %span.clone= "git remote add origin #{@project.url_to_repo}"
+        :preserve
           git push -u origin master
 
     %fieldset
@@ -37,7 +38,8 @@
       %pre.dark
         :preserve
           cd existing_git_repo
-          git remote add origin #{@project.url_to_repo}
+        %span.clone= "git remote add origin #{@project.url_to_repo}"
+        :preserve
           git push -u origin master
 
   - if can? current_user, :remove_project, @project
-- 
GitLab


From 7039fb66fbfd9a4073f2b629d78319156eefd337 Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Fri, 13 Sep 2013 11:37:13 +0200
Subject: [PATCH 089/248] Test.

---
 features/project/create_project.feature  | 11 +++++++++++
 features/steps/project/create_project.rb | 22 ++++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/features/project/create_project.feature b/features/project/create_project.feature
index b7cdfdb818e..395a3218b2b 100644
--- a/features/project/create_project.feature
+++ b/features/project/create_project.feature
@@ -9,3 +9,14 @@ Feature: Create Project
     And fill project form with valid data
     Then I should see project page
     And I should see empty project instuctions
+
+  @javascript
+  Scenario: Empty project instructions
+    Given I sign in as a user
+    When I visit new project page
+    And fill project form with valid data
+    Then I see empty project instuctions
+    And I click on HTTP
+    Then Remote url should update to http link
+    And If I click on SSH
+    Then Remote url should update to ssh link
\ No newline at end of file
diff --git a/features/steps/project/create_project.rb b/features/steps/project/create_project.rb
index 0d9727732c7..b59345e7078 100644
--- a/features/steps/project/create_project.rb
+++ b/features/steps/project/create_project.rb
@@ -17,4 +17,26 @@ class CreateProject < Spinach::FeatureSteps
     page.should have_content "git remote"
     page.should have_content Project.last.url_to_repo
   end
+
+  Then 'I see empty project instuctions' do
+    page.should have_content "git init"
+    page.should have_content "git remote"
+    page.should have_content Project.last.url_to_repo
+  end
+
+  And 'I click on HTTP' do
+    click_button 'HTTP'
+  end
+
+  Then 'Remote url should update to http link' do
+    page.should have_content "git remote add origin #{Project.last.http_url_to_repo}"
+  end
+
+  And 'If I click on SSH' do
+    click_button 'SSH'
+  end
+
+  Then 'Remote url should update to ssh link' do
+    page.should have_content "git remote add origin #{Project.last.url_to_repo}"
+  end
 end
-- 
GitLab


From e2214c8dc0a44413e96447076e88c6f39cd77701 Mon Sep 17 00:00:00 2001
From: Joerg Bornschein <bornschein@fias.uni-frankfurt.de>
Date: Fri, 13 Sep 2013 13:02:37 +0200
Subject: [PATCH 090/248] Fix default settings when creating new Project

---
 app/contexts/projects/create_context.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/contexts/projects/create_context.rb b/app/contexts/projects/create_context.rb
index 9fd24e0eeea..1c60a5de141 100644
--- a/app/contexts/projects/create_context.rb
+++ b/app/contexts/projects/create_context.rb
@@ -18,7 +18,7 @@ module Projects
         snippets_enabled: default_features.snippets,
         merge_requests_enabled: default_features.merge_requests,
         public: default_features.public
-      }
+      }.stringify_keys
 
       @project = Project.new(default_opts.merge(params))
 
-- 
GitLab


From 25969319a8a671bc6cc3647854319c7bab3f7af0 Mon Sep 17 00:00:00 2001
From: Joerg Bornschein <bornschein@fias.uni-frankfurt.de>
Date: Fri, 13 Sep 2013 14:39:04 +0200
Subject: [PATCH 091/248] Add public-project? checkbox to new-project view

---
 app/assets/stylesheets/sections/projects.scss |  6 ++++++
 app/views/projects/new.html.haml              | 14 +++++++-------
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss
index 9c079bbb9ff..f2707f62378 100644
--- a/app/assets/stylesheets/sections/projects.scss
+++ b/app/assets/stylesheets/sections/projects.scss
@@ -36,6 +36,12 @@
   }
 }
 
+.project-public-holder {
+  .help-inline {
+    padding-top: 7px;
+  }
+}
+
 .save-project-loader {
   img {
     margin-top: 50px;
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index ab8efe5e3e1..9055c04b7fb 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -2,13 +2,7 @@
   .project-edit-errors
     = render 'projects/errors'
   .project-edit-content
-    - if Gitlab.config.gitlab.default_projects_features.public
-      %p.slead
-        New projects are public by default. Any signed in user can see your project but cannot commit to it unless granted access.
-    - else
-      %p.slead
-        New projects are private by default. You choose who can see the project and commit to repository.
-    %hr
+
     = form_for @project, remote: true do |f|
       .control-group.project-name-holder
         = f.label :name do
@@ -53,6 +47,12 @@
           %span.light (optional)
         .controls
           = f.text_area :description, placeholder: "awesome project", class: "input-xlarge", rows: 3, maxlength: 250, tabindex: 3
+      .control-group.project-public-holder
+        = f.label :public do
+          %span Public project
+        .controls
+          = f.check_box :public, { :checked => Gitlab.config.gitlab.default_projects_features.public }, true, false
+          %span.help-inline Make project visible to everyone
 
       .form-actions
         = f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4
-- 
GitLab


From 488311788e50d24272bd313438e3287acab2a1ef Mon Sep 17 00:00:00 2001
From: Jakub Zienkiewicz <jakub@zienkiewi.cz>
Date: Fri, 13 Sep 2013 15:38:30 +0200
Subject: [PATCH 092/248] test if commit author receives new note notifications

---
 spec/services/notification_service_spec.rb | 24 +++++++++++-----------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 6a63a8aceb2..a112835d4d0 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -52,10 +52,12 @@ describe NotificationService do
 
       before do
         build_team(note.project)
+        note.stub(:commit_author => @u_committer)
       end
 
       describe :new_note do
         it do
+          should_email(@u_committer.id, note)
           should_email(@u_watcher.id, note)
           should_not_email(@u_mentioned.id, note)
           should_not_email(note.author_id, note)
@@ -65,18 +67,14 @@ describe NotificationService do
         end
 
         it do
-          new_note = create(:note_on_commit,
-                 author: @u_participating,
-                 project_id: note.project_id,
-                 commit_id: note.commit_id,
-                 note: '@mention referenced')
-
-          should_email(@u_watcher.id, new_note)
-          should_email(@u_mentioned.id, new_note)
-          should_not_email(new_note.author_id, new_note)
-          should_not_email(@u_participating.id, new_note)
-          should_not_email(@u_disabled.id, new_note)
-          notification.new_note(new_note)
+          note.update_attribute(:note, '@mention referenced')
+          should_email(@u_committer.id, note)
+          should_email(@u_watcher.id, note)
+          should_email(@u_mentioned.id, note)
+          should_not_email(note.author_id, note)
+          should_not_email(@u_participating.id, note)
+          should_not_email(@u_disabled.id, note)
+          notification.new_note(note)
         end
 
         def should_email(user_id, n)
@@ -240,10 +238,12 @@ describe NotificationService do
     @u_participating = create(:user, notification_level: Notification::N_PARTICIPATING)
     @u_disabled = create(:user, notification_level: Notification::N_DISABLED)
     @u_mentioned = create(:user, username: 'mention', notification_level: Notification::N_PARTICIPATING)
+    @u_committer = create(:user, username: 'committer')
 
     project.team << [@u_watcher, :master]
     project.team << [@u_participating, :master]
     project.team << [@u_disabled, :master]
     project.team << [@u_mentioned, :master]
+    project.team << [@u_committer, :master]
   end
 end
-- 
GitLab


From 458d92e86167c0205bfcc4186601111d608e9560 Mon Sep 17 00:00:00 2001
From: Jakub Zienkiewicz <jakub@zienkiewi.cz>
Date: Fri, 13 Sep 2013 15:38:37 +0200
Subject: [PATCH 093/248] notify commit author of new notes

---
 app/services/notification_service.rb | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 71c25dc1b70..750a71aea6b 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -107,12 +107,6 @@ class NotificationService
 
     opts = { noteable_type: note.noteable_type, project_id: note.project_id }
 
-    if note.commit_id.present?
-      opts.merge!(commit_id: note.commit_id)
-    else
-      opts.merge!(noteable_id: note.noteable_id)
-    end
-
     target = note.noteable
     if target.respond_to?(:participants)
       recipients = target.participants
@@ -120,6 +114,13 @@ class NotificationService
       recipients = note.mentioned_users
     end
 
+    if note.commit_id.present?
+      opts.merge!(commit_id: note.commit_id)
+      recipients << note.commit_author
+    else
+      opts.merge!(noteable_id: note.noteable_id)
+    end
+
     # Get users who left comment in thread
     recipients = recipients.concat(User.where(id: Note.where(opts).pluck(:author_id)))
 
-- 
GitLab


From 3b2d733c071f2624b2aa49411c6b398d52549ee8 Mon Sep 17 00:00:00 2001
From: Spencer <bubbleboy450@gmail.com>
Date: Fri, 13 Sep 2013 19:07:05 -0600
Subject: [PATCH 094/248] Update unicorn.rb.example

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

diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example
index 812fd5b7449..5c933df073a 100644
--- a/config/unicorn.rb.example
+++ b/config/unicorn.rb.example
@@ -35,7 +35,7 @@ timeout 30
 pid "/home/git/gitlab/tmp/pids/unicorn.pid"
 
 # By default, the Unicorn logger will write to stderr.
-# Additionally, ome applications/frameworks log to stderr or stdout,
+# Additionally, some applications/frameworks log to stderr or stdout,
 # so prevent them from going to /dev/null when daemonized here:
 stderr_path "/home/git/gitlab/log/unicorn.stderr.log"
 stdout_path "/home/git/gitlab/log/unicorn.stdout.log"
-- 
GitLab


From c9a2a3f9ab73901899a7d90e492ad252b5f196ef Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sat, 14 Sep 2013 10:14:55 +0300
Subject: [PATCH 095/248] Remove code that was accidently added in
 5dae40f579f66fdc060de633b183ede7bd8b2ce4

---
 lib/gitlab/auth.rb | 66 ----------------------------------------------
 1 file changed, 66 deletions(-)

diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index b1e40defc7f..0f196297477 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -13,72 +13,6 @@ module Gitlab
       end
     end
 
-    def find_for_ldap_auth(auth, signed_in_resource = nil)
-      uid = auth.info.uid
-      provider = auth.provider
-      email = auth.info.email.downcase unless auth.info.email.nil?
-      raise OmniAuth::Error, "LDAP accounts must provide an uid and email address" if uid.nil? or email.nil?
-
-      if @user = User.find_by_extern_uid_and_provider(uid, provider)
-        @user
-      elsif @user = User.find_by_email(email)
-        log.info "Updating legacy LDAP user #{email} with extern_uid => #{uid}"
-        @user.update_attributes(extern_uid: uid, provider: provider)
-        @user
-      else
-        create_from_omniauth(auth, true)
-      end
-    end
-
-    def create_from_omniauth(auth, ldap = false)
-      provider = auth.provider
-      uid = auth.info.uid || auth.uid
-      uid = uid.to_s.force_encoding("utf-8")
-      name = auth.info.name.to_s.force_encoding("utf-8")
-      email = auth.info.email.to_s.downcase unless auth.info.email.nil?
-
-      ldap_prefix = ldap ? '(LDAP) ' : ''
-      raise OmniAuth::Error, "#{ldap_prefix}#{provider} does not provide an email"\
-        " address" if auth.info.email.blank?
-
-      log.info "#{ldap_prefix}Creating user from #{provider} login"\
-        " {uid => #{uid}, name => #{name}, email => #{email}}"
-      password = Devise.friendly_token[0, 8].downcase
-      @user = User.build_user({
-        extern_uid: uid,
-        provider: provider,
-        name: name,
-        username: email.match(/^[^@]*/)[0],
-        email: email,
-        password: password,
-        password_confirmation: password,
-      }, as: :admin)
-      @user.save!
-
-      if Gitlab.config.omniauth['block_auto_created_users'] && !ldap
-        @user.block
-      end
-
-      @user
-    end
-
-    def find_or_new_for_omniauth(auth)
-      provider, uid = auth.provider, auth.uid
-      email = auth.info.email.downcase unless auth.info.email.nil?
-
-      if @user = User.find_by_provider_and_extern_uid(provider, uid)
-        @user
-      elsif @user = User.find_by_email(email)
-        @user.update_attributes(extern_uid: uid, provider: provider)
-        @user
-      else
-        if Gitlab.config.omniauth['allow_single_sign_on']
-          @user = create_from_omniauth(auth)
-          @user
-        end
-      end
-    end
-
     def log
       Gitlab::AppLogger
     end
-- 
GitLab


From 20416c929470630e4ebb87585a4871f2d60fa056 Mon Sep 17 00:00:00 2001
From: Joerg Bornschein <bornschein@fias.uni-frankfurt.de>
Date: Sat, 14 Sep 2013 13:28:15 +0200
Subject: [PATCH 096/248] Use ruby 1.9 hash syntax

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

diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index 9055c04b7fb..0213576927b 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -51,7 +51,7 @@
         = f.label :public do
           %span Public project
         .controls
-          = f.check_box :public, { :checked => Gitlab.config.gitlab.default_projects_features.public }, true, false
+          = f.check_box :public, { checked: Gitlab.config.gitlab.default_projects_features.public }, true, false
           %span.help-inline Make project visible to everyone
 
       .form-actions
-- 
GitLab


From 93b7e3b725a69baf021e7ce5242b9319baa18c51 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sat, 14 Sep 2013 18:24:55 +0300
Subject: [PATCH 097/248] Update CHANGELOG with new entries for 6.1

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

diff --git a/CHANGELOG b/CHANGELOG
index 5c27e93ff64..7572837f883 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -13,6 +13,10 @@ v 6.1.0
   - Remove deprecated classes and rake tasks
   - Add event filter for group and project show pages
   - Add links to create branch/tag from project home page
+  - Add public-project? checkbox to new-project view
+  - Improved compare page. Added link to proceed into Merge Request
+  - Send email to user when he was added to group
+  - New landing page when you have 0 projects
 
 v 6.0.0
   - Feature: Replace teams with group membership
-- 
GitLab


From bddb24eb07032fc0f3581de1a35dd4f431e4e10c Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sat, 14 Sep 2013 18:25:42 +0300
Subject: [PATCH 098/248] Let it be 6.1.0.rc1

---
 VERSION | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/VERSION b/VERSION
index f5999028a39..7c93db420c1 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-6.1.0.beta1
+6.1.0.rc1
-- 
GitLab


From 7057ebe4d91dcf619bb9e9bab57c8ad845bbf5c2 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sat, 14 Sep 2013 20:51:16 +0300
Subject: [PATCH 099/248] Fix setting default values for user

---
 app/models/user.rb | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/app/models/user.rb b/app/models/user.rb
index ea1b9419288..c1026a44f87 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -200,17 +200,18 @@ class User < ActiveRecord::Base
     end
 
     def build_user(attrs = {}, options= {})
-      user = User.new(defaults.merge(attrs), options)
-      # if not as: :admin force default settings
-      user.with_defaults unless options[:as] == :admin
-      user
+      if options[:as] == :admin
+        User.new(defaults.merge(attrs.symbolize_keys), options)
+      else
+        User.new(attrs, options).with_defaults
+      end
     end
 
     def defaults
       {
         projects_limit: Gitlab.config.gitlab.default_projects_limit,
         can_create_group: Gitlab.config.gitlab.default_can_create_group,
-        theme_id: Gitlab::Theme::BASIC
+        theme_id: Gitlab::Theme::MARS
       }
     end
   end
@@ -384,8 +385,10 @@ class User < ActiveRecord::Base
   end
 
   def with_defaults
-    User.defaults.each do |k,v|
-      self.send("#{k}=",v)
+    User.defaults.each do |k, v|
+      self.send("#{k}=", v)
     end
+
+    self
   end
 end
-- 
GitLab


From db265778eb6ce2841b2be8ee0e0cd76afcc936a4 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sat, 14 Sep 2013 20:55:33 +0300
Subject: [PATCH 100/248] Extend user infiormation displayed on admin user page

---
 app/views/admin/users/show.html.haml | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 95257a4594e..3df9903e409 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -33,7 +33,14 @@
           %span.light Email:
           %strong
             = mail_to @user.email
-
+        %li
+          %span.light Can create groups:
+          %strong
+            = @user.can_create_group ? "Yes" : "No"
+        %li
+          %span.light Personal projects limit:
+          %strong
+            = @user.projects_limit
         %li
           %span.light Member since:
           %strong
-- 
GitLab


From 53279d93c1ef3f67f98c2d9e14e07a84a205073e Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sat, 14 Sep 2013 21:18:01 +0300
Subject: [PATCH 101/248] Fix 500 error on admin->project page

---
 app/assets/stylesheets/sections/dashboard.scss | 3 +--
 app/views/admin/projects/show.html.haml        | 4 ++--
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/app/assets/stylesheets/sections/dashboard.scss b/app/assets/stylesheets/sections/dashboard.scss
index 15bfad96f6c..61331cee413 100644
--- a/app/assets/stylesheets/sections/dashboard.scss
+++ b/app/assets/stylesheets/sections/dashboard.scss
@@ -66,7 +66,7 @@
 }
 
 .project-row, .group-row {
-  padding: 12px 15px !important;
+  padding: 10px 15px !important;
 
   .namespace-name {
     color: #666;
@@ -77,7 +77,6 @@
     font-size: 16px;
   }
 
-
   .arrow {
     float: right;
     padding: 10px 5px;
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 4544a9aa190..cecc84fe093 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -99,7 +99,7 @@
       %ul.well-list.team_members
         - @project.users_projects.each do |users_project|
           - user = users_project.user
-          %li
+          %li.users_project
             %strong
               = link_to user.name, admin_user_path(user)
             .pull-right
@@ -107,5 +107,5 @@
                 %span.light Owner
               - else
                 %span.light= users_project.human_access
-                = link_to admin_project_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "btn btn-small btn-remove" do
+                = link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, remote: true, class: "btn btn-small btn-remove" do
                   %i.icon-remove
-- 
GitLab


From 19aca1b3cd20e7b188d4e816fc356c68f8682054 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sat, 14 Sep 2013 22:01:31 +0300
Subject: [PATCH 102/248] Fix tests

---
 spec/models/user_spec.rb        | 20 +++++++++++++-------
 spec/requests/api/users_spec.rb |  2 +-
 2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 330d22cf962..79915daa463 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -209,6 +209,7 @@ describe User do
 
     describe 'without defaults' do
       let(:user) { User.new }
+
       it "should not apply defaults to user" do
         user.projects_limit.should == 10
         user.can_create_group.should be_true
@@ -218,19 +219,21 @@ describe User do
     context 'as admin' do
       describe 'with defaults' do
         let(:user) { User.build_user({}, as: :admin) }
+
         it "should apply defaults to user" do
           user.projects_limit.should == 42
           user.can_create_group.should be_false
-          user.theme_id.should == Gitlab::Theme::BASIC
+          user.theme_id.should == Gitlab::Theme::MARS
         end
       end
 
       describe 'with default overrides' do
-        let(:user) { User.build_user({projects_limit: 123, can_create_group: true, can_create_team: true, theme_id: Gitlab::Theme::MARS}, as: :admin) }
+        let(:user) { User.build_user({projects_limit: 123, can_create_group: true, can_create_team: true, theme_id: Gitlab::Theme::BASIC}, as: :admin) }
+
         it "should apply defaults to user" do
           user.projects_limit.should == 123
           user.can_create_group.should be_true
-          user.theme_id.should == Gitlab::Theme::MARS
+          user.theme_id.should == Gitlab::Theme::BASIC
         end
       end
     end
@@ -238,26 +241,29 @@ describe User do
     context 'as user' do
       describe 'with defaults' do
         let(:user) { User.build_user }
+
         it "should apply defaults to user" do
           user.projects_limit.should == 42
           user.can_create_group.should be_false
-          user.theme_id.should == Gitlab::Theme::BASIC
+          user.theme_id.should == Gitlab::Theme::MARS
         end
       end
 
       describe 'with default overrides' do
-        let(:user) { User.build_user(projects_limit: 123, can_create_group: true, theme_id: Gitlab::Theme::MARS) }
+        let(:user) { User.build_user(projects_limit: 123, can_create_group: true, theme_id: Gitlab::Theme::BASIC) }
+
         it "should apply defaults to user" do
           user.projects_limit.should == 42
           user.can_create_group.should be_false
-          user.theme_id.should == Gitlab::Theme::BASIC
+          user.theme_id.should == Gitlab::Theme::MARS
         end
       end
     end
   end
 
   describe 'by_username_or_id' do
-    let(:user1){create(:user, username: 'foo')}
+    let(:user1) { create(:user, username: 'foo') }
+
     it "should get the correct user" do
       User.by_username_or_id(user1.id).should == user1
       User.by_username_or_id('foo').should == user1
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index e42c0567ef6..2fced3ec945 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -66,7 +66,7 @@ describe API::API do
       }.to change { User.count }.by(1)
       user = User.find_by_username(attr[:username])
       user.projects_limit.should == limit
-      user.theme_id.should == Gitlab::Theme::BASIC
+      user.theme_id.should == Gitlab::Theme::MARS
       Gitlab.config.gitlab.unstub(:default_projects_limit)
     end
 
-- 
GitLab


From fa420fd0a9d84e147343e3870c440bf43ff72179 Mon Sep 17 00:00:00 2001
From: Ash Wilson <smashwilson@gmail.com>
Date: Sun, 15 Sep 2013 15:46:06 -0400
Subject: [PATCH 103/248] Don't quote the default issue closing regex.

It turns out that regex escapes and YAML quoted-scalar escapes don't play
nicely together.
---
 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 0d68879da6d..ffe333a1f8b 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -49,7 +49,7 @@ production: &base
     ## Automatic issue closing
     # If a commit message matches this regular express, all issues referenced from the matched text will be closed
     # if it's pushed to a project's default branch.
-    # issue_closing_pattern: "^([Cc]loses|[Ff]ixes) +#\d+"
+    # issue_closing_pattern: ^([Cc]loses|[Ff]ixes) +#\d+
 
     ## Default project features settings
     default_projects_features:
-- 
GitLab


From a76e719fb1c53741c687f3d7ff7c16eff9cc6463 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 16 Sep 2013 13:33:34 +0300
Subject: [PATCH 104/248] Update gitlab_git to version 2.2.0. Fixes invalid
 diff in Compare

---
 Gemfile                                        | 2 +-
 Gemfile.lock                                   | 4 ++--
 app/controllers/projects/compare_controller.rb | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Gemfile b/Gemfile
index b201969bc36..aa20ec58d86 100644
--- a/Gemfile
+++ b/Gemfile
@@ -23,7 +23,7 @@ gem 'omniauth-github'
 
 # Extracting information from a git repository
 # Provide access to Gitlab::Git library
-gem "gitlab_git", '2.1.1'
+gem "gitlab_git", '2.2.0'
 
 # Ruby/Rack Git Smart-HTTP Server Handler
 gem 'gitlab-grack', '~> 1.0.1', require: 'grack'
diff --git a/Gemfile.lock b/Gemfile.lock
index ddca83d38c2..a360e063eff 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -179,7 +179,7 @@ GEM
     gitlab-pygments.rb (0.3.2)
       posix-spawn (~> 0.3.6)
       yajl-ruby (~> 1.1.0)
-    gitlab_git (2.1.1)
+    gitlab_git (2.2.0)
       activesupport (~> 3.2.13)
       github-linguist (~> 2.3.4)
       gitlab-grit (~> 2.6.0)
@@ -572,7 +572,7 @@ DEPENDENCIES
   gitlab-gollum-lib (~> 1.0.1)
   gitlab-grack (~> 1.0.1)
   gitlab-pygments.rb (~> 0.3.2)
-  gitlab_git (= 2.1.1)
+  gitlab_git (= 2.2.0)
   gitlab_meta (= 6.0)
   gitlab_omniauth-ldap (= 1.0.3)
   gon
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index d7e660dac22..b7531e2cefb 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -8,7 +8,7 @@ class Projects::CompareController < Projects::ApplicationController
   end
 
   def show
-    compare = Gitlab::Git::Compare.new(project.repository, params[:from], params[:to])
+    compare = Gitlab::Git::Compare.new(@repository.raw_repository, params[:from], params[:to])
 
     @commits       = compare.commits
     @commit        = compare.commit
-- 
GitLab


From ec5c4a4a6515369fe5dd0aff4123d4655bf49fd7 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 16 Sep 2013 14:04:22 +0300
Subject: [PATCH 105/248] Update docs to use 6-1-stable branch

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

diff --git a/doc/install/installation.md b/doc/install/installation.md
index 69130a06e0c..71a587d2ee3 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -153,10 +153,10 @@ To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install
     cd /home/git/gitlab
 
     # Checkout to stable release
-    sudo -u git -H git checkout 6-0-stable
+    sudo -u git -H git checkout 6-1-stable
 
 **Note:**
-You can change `6-0-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
+You can change `6-1-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
 
 ## Configure it
 
-- 
GitLab


From f07252e2861e971cfacd0b350f0f777789bce554 Mon Sep 17 00:00:00 2001
From: Yatish Mehta <yatishmehta27@gmail.com>
Date: Mon, 16 Sep 2013 19:19:04 +0530
Subject: [PATCH 106/248] Added .ruby-version & .ruby-gemset in .gitignore

---
 .gitignore | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.gitignore b/.gitignore
index b1dc17929f2..683e6c45a2b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,8 @@ coverage/*
 backups/*
 *.swp
 public/uploads/
+.ruby-version
+.ruby-gemset
 .rvmrc
 .rbenv-version
 .directory
-- 
GitLab


From aea1dcb6a1434e128e48e854549a959d33b567bb Mon Sep 17 00:00:00 2001
From: Spencer Owen <spencerowen@Spencers-MacBook-Pro.local>
Date: Mon, 16 Sep 2013 23:52:26 -0600
Subject: [PATCH 107/248] Corrects the update document to match the version of
 gitshell specified in the install document (1.7.1)

---
 doc/update/6.0-to-6.1.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/update/6.0-to-6.1.md b/doc/update/6.0-to-6.1.md
index dcd09be72f7..5076d0497e6 100644
--- a/doc/update/6.0-to-6.1.md
+++ b/doc/update/6.0-to-6.1.md
@@ -36,7 +36,7 @@ sudo -u git -H git checkout 6-1-stable
 ```bash
 cd /home/git/gitlab-shell
 sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.0
+sudo -u git -H git checkout v1.7.1
 ```
 
 ### 4. Install libs, migrations, etc.
-- 
GitLab


From b956011d9b6fbd39c2d8195fb123e9c697386fba Mon Sep 17 00:00:00 2001
From: Hiroyuki Sato <sathiroyuki@gmail.com>
Date: Tue, 17 Sep 2013 22:12:10 +0900
Subject: [PATCH 108/248] Drop support of root namespace in model

---
 app/models/project.rb                         |  7 ++-----
 .../issues/bulk_update_context_spec.rb        |  5 ++++-
 spec/contexts/projects_create_context_spec.rb |  6 +++++-
 spec/models/project_spec.rb                   |  1 +
 spec/requests/api/internal_spec.rb            |  2 ++
 spec/requests/api/issues_spec.rb              |  2 ++
 spec/requests/api/notes_spec.rb               |  2 ++
 .../services/project_transfer_service_spec.rb | 20 +------------------
 8 files changed, 19 insertions(+), 26 deletions(-)

diff --git a/app/models/project.rb b/app/models/project.rb
index 6c4f3075e1c..f4d915179e8 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -83,6 +83,7 @@ class Project < ActiveRecord::Base
             :wiki_enabled, inclusion: { in: [true, false] }
   validates :issues_tracker_id, length: { within: 0..255 }
 
+  validates :namespace, presence: true
   validates_uniqueness_of :name, scope: :namespace_id
   validates_uniqueness_of :path, scope: :namespace_id
 
@@ -165,11 +166,7 @@ class Project < ActiveRecord::Base
   end
 
   def to_param
-    if namespace
-      namespace.path + "/" + path
-    else
-      path
-    end
+    namespace.path + "/" + path
   end
 
   def web_url
diff --git a/spec/contexts/issues/bulk_update_context_spec.rb b/spec/contexts/issues/bulk_update_context_spec.rb
index 0966ee35745..058e43ba090 100644
--- a/spec/contexts/issues/bulk_update_context_spec.rb
+++ b/spec/contexts/issues/bulk_update_context_spec.rb
@@ -1,6 +1,8 @@
 require 'spec_helper'
 
 describe Issues::BulkUpdateContext do
+  before(:each) { ActiveRecord::Base.observers.enable(:user_observer) }
+  after(:each) { ActiveRecord::Base.observers.disable(:user_observer) }
 
   let(:issue) {
     create(:issue, project: @project)
@@ -9,7 +11,8 @@ describe Issues::BulkUpdateContext do
   before do
     @user = create :user
     opts = {
-      name: "GitLab"
+      name: "GitLab",
+      namespace: @user.namespace
     }
     @project = Projects::CreateContext.new(@user, opts).execute
   end
diff --git a/spec/contexts/projects_create_context_spec.rb b/spec/contexts/projects_create_context_spec.rb
index be492585b27..7b5fa530a8a 100644
--- a/spec/contexts/projects_create_context_spec.rb
+++ b/spec/contexts/projects_create_context_spec.rb
@@ -1,11 +1,15 @@
 require 'spec_helper'
 
 describe Projects::CreateContext do
+  before(:each) { ActiveRecord::Base.observers.enable(:user_observer) }
+  after(:each) { ActiveRecord::Base.observers.disable(:user_observer) }
+
   describe :create_by_user do
     before do
       @user = create :user
       @opts = {
-        name: "GitLab"
+        name: "GitLab",
+        namespace: @user.namespace
       }
     end
 
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 3bac142f4e2..c3d2bf5d4a6 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -67,6 +67,7 @@ describe Project do
     it { should ensure_length_of(:description).is_within(0..2000) }
     it { should validate_presence_of(:creator) }
     it { should ensure_length_of(:issues_tracker_id).is_within(0..255) }
+    it { should validate_presence_of(:namespace) }
 
     it "should not allow new projects beyond user limits" do
       project2 = build(:project)
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index 028617aa08e..e8870f4d5d8 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -2,6 +2,8 @@ require 'spec_helper'
 
 describe API::API do
   include ApiHelpers
+  before(:each) { ActiveRecord::Base.observers.enable(:user_observer) }
+  after(:each) { ActiveRecord::Base.observers.disable(:user_observer) }
 
   let(:user) { create(:user) }
   let(:key) { create(:key, user: user) }
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index d5f75367e4a..a97d6a282a9 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -2,6 +2,8 @@ require 'spec_helper'
 
 describe API::API do
   include ApiHelpers
+  before(:each) { ActiveRecord::Base.observers.enable(:user_observer) }
+  after(:each) { ActiveRecord::Base.observers.disable(:user_observer) }
 
   let(:user) { create(:user) }
   let!(:project) { create(:project, namespace: user.namespace ) }
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index 48a2d111f8c..ba18b123039 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -2,6 +2,8 @@ require 'spec_helper'
 
 describe API::API do
   include ApiHelpers
+  before(:each) { ActiveRecord::Base.observers.enable(:user_observer) }
+  after(:each) { ActiveRecord::Base.observers.disable(:user_observer) }
 
   let(:user) { create(:user) }
   let!(:project) { create(:project, namespace: user.namespace ) }
diff --git a/spec/services/project_transfer_service_spec.rb b/spec/services/project_transfer_service_spec.rb
index bc26403b7f4..109b429967e 100644
--- a/spec/services/project_transfer_service_spec.rb
+++ b/spec/services/project_transfer_service_spec.rb
@@ -21,25 +21,7 @@ describe ProjectTransferService do
     let(:user) { create(:user) }
     let(:project) { create(:project, namespace: user.namespace) }
 
-    before do
-      @result = service.transfer(project, nil)
-    end
-
-
-    it { @result.should be_true }
-    it { project.namespace.should == nil }
-  end
-
-  context 'no namespace -> namespace' do
-    let(:project) { create(:project) }
-    let(:user) { create(:user) }
-
-    before do
-      @result = service.transfer(project, user.namespace)
-    end
-
-    it { @result.should be_true }
-    it { project.namespace.should == user.namespace }
+    it { lambda{service.transfer(project, nil)}.should raise_error(ActiveRecord::RecordInvalid) }
   end
 
   def service
-- 
GitLab


From cb68ba59c770064df5bf6959d5a092a315381db8 Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Tue, 17 Sep 2013 16:37:36 -0400
Subject: [PATCH 109/248] Don't show users password change page if ldap users

---
 app/controllers/application_controller.rb     |  2 +-
 features/profile/profile.feature              |  1 +
 features/steps/profile/profile.rb             |  5 +++
 .../application_controller_spec.rb            | 33 +++++++++++++++++++
 4 files changed, 40 insertions(+), 1 deletion(-)
 create mode 100644 spec/controllers/application_controller_spec.rb

diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index b93bf0f98eb..d974600dcc1 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -151,7 +151,7 @@ class ApplicationController < ActionController::Base
   end
 
   def check_password_expiration
-    if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now
+    if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now  && !current_user.ldap_user?
       redirect_to new_profile_password_path and return
     end
   end
diff --git a/features/profile/profile.feature b/features/profile/profile.feature
index 53a93b0f908..3b61552a73d 100644
--- a/features/profile/profile.feature
+++ b/features/profile/profile.feature
@@ -18,6 +18,7 @@ Feature: Profile
 
   Scenario: My password is expired
     Given my password is expired
+    And I am not an ldap user
     And I visit profile account page
     Then I redirected to expired password page
     And I submit new password
diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb
index 23eeac447b0..6944977c3ff 100644
--- a/features/steps/profile/profile.rb
+++ b/features/steps/profile/profile.rb
@@ -91,6 +91,11 @@ class Profile < Spinach::FeatureSteps
     current_user.update_attributes(password_expires_at: Time.now - 1.hour)
   end
 
+  step "I am not an ldap user" do
+    current_user.update_attributes(extern_uid: nil,  provider: '')
+    current_user.ldap_user?.should be_false
+  end
+
   step 'I redirected to expired password page' do
     current_path.should == new_profile_password_path
   end
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
new file mode 100644
index 00000000000..d528d12c66c
--- /dev/null
+++ b/spec/controllers/application_controller_spec.rb
@@ -0,0 +1,33 @@
+require 'spec_helper'
+
+describe ApplicationController do
+  describe '#check_password_expiration' do
+    let(:user) { create(:user) }
+    let(:controller) { ApplicationController.new }
+
+    it 'should redirect if the user is over their password expiry' do
+      user.password_expires_at = Time.new(2002)
+      user.ldap_user?.should be_false
+      controller.stub!(:current_user).and_return(user)
+      controller.should_receive(:redirect_to)
+      controller.should_receive(:new_profile_password_path)
+      controller.send(:check_password_expiration)
+    end
+
+    it 'should not redirect if the user is under their password expiry' do
+      user.password_expires_at = Time.now + 20010101
+      user.ldap_user?.should be_false
+      controller.stub!(:current_user).and_return(user)
+      controller.should_not_receive(:redirect_to)
+      controller.send(:check_password_expiration)
+    end
+
+    it 'should not redirect if the user is over their password expiry but they are an ldap user' do
+      user.password_expires_at = Time.new(2002)
+      user.stub!(:ldap_user?).and_return(true)
+      controller.stub!(:current_user).and_return(user)
+      controller.should_not_receive(:redirect_to)
+      controller.send(:check_password_expiration)
+    end
+  end
+end
\ No newline at end of file
-- 
GitLab


From 85623c8413acddd4f876421620c0938e9df87ec1 Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Wed, 18 Sep 2013 09:35:38 +0200
Subject: [PATCH 110/248] Add author and issue id warning.

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

diff --git a/CHANGELOG b/CHANGELOG
index 7572837f883..52522394e00 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,13 +1,15 @@
 v 6.1.0
+  - Project specific IDs for issues, mr, milestones
+    Above items will get a new id and for example all bookmarked issue urls will change.
+    Old issue urls are redirected to the new one if the issue id is too high for an internal id.
   - Description field added to Merge Request
   - API: Sudo api calls (Izaak Alpert)
   - API: Group membership api (Izaak Alpert)
   - Improved commit diff
   - Improved large commit handling (Boyan Tabakov)
   - Rewrite: Init script now less prone to errors and keeps better track of the service.
-  - Link issues, merge requests, and commits when they reference each other with GFM
+  - Link issues, merge requests, and commits when they reference each other with GFM (Ash Wilson)
   - Close issues automatically when pushing commits with a special message
-  - Project internal ids for issues, mr, milestones
   - Improve user removal from admin area
   - Invalidate events cache when project was moved
   - Remove deprecated classes and rake tasks
-- 
GitLab


From efcc45a187fb320bfe75a550c756a1091b5d0d28 Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Thu, 19 Sep 2013 10:45:31 +0200
Subject: [PATCH 111/248] README improved. Removed travis badge

---
 README.md | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index a4c5c0d0534..ce0f4a8a1c5 100644
--- a/README.md
+++ b/README.md
@@ -20,8 +20,6 @@
 
 * [![build status](http://ci.gitlab.org/projects/1/status.png?ref=master)](http://ci.gitlab.org/projects/1?ref=master) on ci.gitlab.org (master branch)
 
-* [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://travis-ci.org/gitlabhq/gitlabhq) on travis-ci.org (master branch)
-
 * [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.png)](https://codeclimate.com/github/gitlabhq/gitlabhq)
 
 * [![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.png)](https://gemnasium.com/gitlabhq/gitlabhq) this button can be yellow (small updates are available) but must not be red (a security fix or an important update is available), gems are updated in major releases of GitLab.
@@ -39,11 +37,10 @@
 ### Requirements
 
 * Ubuntu/Debian**
-* ruby 1.9.3
+* ruby 1.9.3+
+* git 1.7.10+
+* redis 2.0+
 * MySQL or PostgreSQL
-* git
-* gitlab-shell
-* redis
 
 ** More details are in the [requirements doc](doc/install/requirements.md)
 
-- 
GitLab


From c84726da54c99dfb278a25e18ba864131daa9de4 Mon Sep 17 00:00:00 2001
From: Axilleas Pipinellis <axilleas@archlinux.gr>
Date: Thu, 19 Sep 2013 16:36:37 +0300
Subject: [PATCH 112/248] Add author of new init script

---
 CHANGELOG | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG b/CHANGELOG
index 52522394e00..e955925138c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -7,7 +7,7 @@ v 6.1.0
   - API: Group membership api (Izaak Alpert)
   - Improved commit diff
   - Improved large commit handling (Boyan Tabakov)
-  - Rewrite: Init script now less prone to errors and keeps better track of the service.
+  - Rewrite: Init script now less prone to errors and keeps better track of the service (Rovanion Luckey)
   - Link issues, merge requests, and commits when they reference each other with GFM (Ash Wilson)
   - Close issues automatically when pushing commits with a special message
   - Improve user removal from admin area
-- 
GitLab


From a43664f9392c051c3d034b5f602dfa2e1335a27b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Schl=C3=BCter?= <github@jan-schlueter.de>
Date: Thu, 19 Sep 2013 19:25:40 +0200
Subject: [PATCH 113/248] remove old assets before compiling

---
 doc/update/6.0-to-6.1.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/doc/update/6.0-to-6.1.md b/doc/update/6.0-to-6.1.md
index 5076d0497e6..2fb762e467a 100644
--- a/doc/update/6.0-to-6.1.md
+++ b/doc/update/6.0-to-6.1.md
@@ -53,6 +53,7 @@ sudo -u git -H bundle install --without development test mysql --deployment
 
 sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
 sudo -u git -H bundle exec rake migrate_iids RAILS_ENV=production
+sudo -u git -H bundle exec rake assets:clean RAILS_ENV=production
 sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
 sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
 ```
-- 
GitLab


From abb8672871bf2d858238d07bce8f1f6cdc5f2111 Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Fri, 20 Sep 2013 11:39:12 -0400
Subject: [PATCH 114/248] Prevent empty public projects from throwing
 exceptions

GITLAB-1279 (GITLAB-1264)

Change-Id: Ifb5b4313bc91fae720f8ef5c36152c45e9d38934
---
 app/controllers/public/projects_controller.rb | 12 ++--
 app/views/public/projects/show.html.haml      | 57 ++++++++++---------
 features/public/public_projects.feature       |  5 ++
 features/steps/public/projects_feature.rb     | 18 ++++++
 4 files changed, 60 insertions(+), 32 deletions(-)

diff --git a/app/controllers/public/projects_controller.rb b/app/controllers/public/projects_controller.rb
index 85216cd3271..3504bd3f1a5 100644
--- a/app/controllers/public/projects_controller.rb
+++ b/app/controllers/public/projects_controller.rb
@@ -1,7 +1,7 @@
 class Public::ProjectsController < ApplicationController
   skip_before_filter :authenticate_user!,
-    :reject_blocked, :set_current_user_for_observers,
-    :add_abilities
+                     :reject_blocked, :set_current_user_for_observers,
+                     :add_abilities
 
   layout 'public'
 
@@ -16,9 +16,11 @@ class Public::ProjectsController < ApplicationController
     render_404 and return unless @project
 
     @repository = @project.repository
-    @recent_tags = @repository.tags.first(10)
+    unless @project.empty_repo?
+      @recent_tags = @repository.tags.first(10)
 
-    @commit = @repository.commit(params[:ref])
-    @tree = Tree.new(@repository, @commit.id)
+      @commit = @repository.commit(params[:ref])
+      @tree = Tree.new(@repository, @commit.id)
+    end
   end
 end
diff --git a/app/views/public/projects/show.html.haml b/app/views/public/projects/show.html.haml
index c4d8a4f5a5f..195b9bc07d2 100644
--- a/app/views/public/projects/show.html.haml
+++ b/app/views/public/projects/show.html.haml
@@ -15,32 +15,35 @@
 
 %br
 .row
-  .span9
-    = render 'tree', tree: @tree
-  .span3
-    %h5 Repository:
-    %div
-      %p
-        %span.light Bare size is
-        #{@project.repository.size} MB
+  - unless @project.empty_repo?
+    .span9
+      = render 'tree', tree: @tree
+    .span3
+      %h5 Repository:
+      %div
+        %p
+          %span.light Bare size is
+          #{@project.repository.size} MB
 
-      %p
-        = pluralize(@repository.round_commit_count, 'commit')
-      %p
-        = pluralize(@repository.branch_names.count, 'branch')
-      %p
-        = pluralize(@repository.tag_names.count, 'tag')
+        %p
+          = pluralize(@repository.round_commit_count, 'commit')
+        %p
+          = pluralize(@repository.branch_names.count, 'branch')
+        %p
+          = pluralize(@repository.tag_names.count, 'tag')
 
-    - if @recent_tags.present?
-      %hr
-      %h5 Most Recent Tags:
-      %ul.unstyled
-        - @recent_tags.each do |tag|
-          %li
-            %p
-              %i.icon-tag
-              %strong= tag.name
-              %small.light.pull-right
-                %i.icon-calendar
-                  = time_ago_in_words(tag.commit.committed_date)
-                ago
+      - if @recent_tags.present?
+        %hr
+        %h5 Most Recent Tags:
+        %ul.unstyled
+          - @recent_tags.each do |tag|
+            %li
+              %p
+                %i.icon-tag
+                %strong= tag.name
+                %small.light.pull-right
+                  %i.icon-calendar
+                    = time_ago_in_words(tag.commit.committed_date)
+                  ago
+  - else
+    = 'Empty Repository'
diff --git a/features/public/public_projects.feature b/features/public/public_projects.feature
index c4f1b6203e7..1866d3f47fe 100644
--- a/features/public/public_projects.feature
+++ b/features/public/public_projects.feature
@@ -12,3 +12,8 @@ Feature: Public Projects Feature
     When I visit public page for "Community" project
     Then I should see public project details
     And I should see project readme
+
+  Scenario: I visit an empty public project page
+    Given public empty project "Empty Public Project"
+    When I visit empty public project page
+    Then I should see empty public project details
\ No newline at end of file
diff --git a/features/steps/public/projects_feature.rb b/features/steps/public/projects_feature.rb
index 8d612498fb9..2268e9b9c5e 100644
--- a/features/steps/public/projects_feature.rb
+++ b/features/steps/public/projects_feature.rb
@@ -9,6 +9,11 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps
     page.should_not have_content "Enterprise"
   end
 
+  step 'I should see project "Empty Public Project"' do
+    page.should have_content "Empty Public Project"
+    puts page.save_page('foo.html')
+  end
+
   step 'I should see public project details' do
     page.should have_content '32 branches'
     page.should have_content '16 tags'
@@ -22,6 +27,19 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps
     create :project_with_code, name: 'Community', public: true
   end
 
+  step 'public empty project "Empty Public Project"' do
+    create :project, name: 'Empty Public Project', public: true
+  end
+
+  step 'I visit empty public project page' do
+    project = Project.find_by_name('Empty Public Project')
+    visit public_project_path(project)
+  end
+
+  step 'I should see empty public project details' do
+    page.should have_content 'Empty Repository'
+  end
+
   step 'private project "Enterprise"' do
     create :project, name: 'Enterprise'
   end
-- 
GitLab


From fdaf362092cb163c53ed9cd57d74300d517fc21a Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Sat, 21 Sep 2013 18:54:18 +0200
Subject: [PATCH 115/248] Update gitlab_git to version 2.3.1

---
 Gemfile      | 2 +-
 Gemfile.lock | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Gemfile b/Gemfile
index aa20ec58d86..ccefe0af7a5 100644
--- a/Gemfile
+++ b/Gemfile
@@ -23,7 +23,7 @@ gem 'omniauth-github'
 
 # Extracting information from a git repository
 # Provide access to Gitlab::Git library
-gem "gitlab_git", '2.2.0'
+gem "gitlab_git", '2.3.1'
 
 # Ruby/Rack Git Smart-HTTP Server Handler
 gem 'gitlab-grack', '~> 1.0.1', require: 'grack'
diff --git a/Gemfile.lock b/Gemfile.lock
index a360e063eff..9de7a0f876b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -179,7 +179,7 @@ GEM
     gitlab-pygments.rb (0.3.2)
       posix-spawn (~> 0.3.6)
       yajl-ruby (~> 1.1.0)
-    gitlab_git (2.2.0)
+    gitlab_git (2.3.1)
       activesupport (~> 3.2.13)
       github-linguist (~> 2.3.4)
       gitlab-grit (~> 2.6.0)
@@ -421,7 +421,7 @@ GEM
       rspec-expectations (~> 2.13.0)
       rspec-mocks (~> 2.13.0)
     ruby-hmac (0.4.0)
-    ruby-progressbar (1.1.1)
+    ruby-progressbar (1.2.0)
     rubyntlm (0.1.1)
     rubyzip (0.9.9)
     safe_yaml (0.9.3)
@@ -572,7 +572,7 @@ DEPENDENCIES
   gitlab-gollum-lib (~> 1.0.1)
   gitlab-grack (~> 1.0.1)
   gitlab-pygments.rb (~> 0.3.2)
-  gitlab_git (= 2.2.0)
+  gitlab_git (= 2.3.1)
   gitlab_meta (= 6.0)
   gitlab_omniauth-ldap (= 1.0.3)
   gon
-- 
GitLab


From 741eabbeb52a18bcf1fbb7523a1c0d82cd20f007 Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Sat, 21 Sep 2013 20:33:34 +0200
Subject: [PATCH 116/248] Restyle tree table UI

---
 app/assets/stylesheets/gitlab_bootstrap/tables.scss | 4 ++--
 app/assets/stylesheets/sections/tree.scss           | 6 +++++-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/app/assets/stylesheets/gitlab_bootstrap/tables.scss b/app/assets/stylesheets/gitlab_bootstrap/tables.scss
index a1a5139cda9..29ec1b584bd 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/tables.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/tables.scss
@@ -17,11 +17,11 @@ table {
   }
 
   th {
-    font-weight: bold;
+    font-weight: normal;
+    font-size: 15px;
     vertical-align: middle;
     border-bottom: 1px solid #CCC;
     text-shadow: 0 1px 1px #fff;
-    @include bg-dark-gray-gradient;
 
     ul.nav {
       text-shadow: none;
diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss
index 850ed831dfb..ff31265bac1 100644
--- a/app/assets/stylesheets/sections/tree.scss
+++ b/app/assets/stylesheets/sections/tree.scss
@@ -57,13 +57,17 @@
   }
 
   .tree-table {
+    border: none;
+
     th .btn {
       margin: -2px -1px;
       padding: 2px 10px;
     }
     td {
       line-height: 20px;
-      background: #fafafa;
+      background: #fff !important;
+      border-left: none;
+      border-right: none;
     }
   }
 
-- 
GitLab


From 1970a948e9f3da2659bea618de4dd1b49f6249e8 Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Sat, 21 Sep 2013 20:59:46 +0200
Subject: [PATCH 117/248] Restyle event title

---
 app/assets/stylesheets/sections/events.scss | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss
index fd5c80f988c..39b2ad7a09c 100644
--- a/app/assets/stylesheets/sections/events.scss
+++ b/app/assets/stylesheets/sections/events.scss
@@ -46,8 +46,8 @@
   border-bottom: 1px solid #eee;
   .event-title {
     color: #333;
-    font-weight: bold;
-    font-size: 14px;
+    font-weight: normal;
+    font-size: 15px;
     .author_name {
       color: #333;
     }
-- 
GitLab


From a7179c6515327ff829b0fd585c92ce62cd581858 Mon Sep 17 00:00:00 2001
From: Hiroyuki Sato <sathiroyuki@gmail.com>
Date: Sun, 22 Sep 2013 06:46:36 +0900
Subject: [PATCH 118/248] Fix API::MergeRequest

Fixes #5144 Refs #4996
---
 lib/api/merge_requests.rb                |  2 +-
 spec/requests/api/merge_requests_spec.rb | 52 ++++++++++++------------
 2 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 4a521c3daeb..d690f1d07e7 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -4,7 +4,7 @@ module API
     before { authenticate! }
     before { Thread.current[:current_user] = current_user }
 
-    resource :projects, requirements: { id: /[a-zA-Z.0-9_\-]+\/[a-zA-Z.0-9_\-]+/ } do
+    resource :projects do
       helpers do
         def handle_merge_request_errors!(errors)
           if errors[:project_access].any?
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index fb4a7d9bc19..2f11f562aa1 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -14,14 +14,14 @@ describe API::API do
   describe "GET /projects/:id/merge_requests" do
     context "when unauthenticated" do
       it "should return authentication error" do
-        get api("/projects/#{project.to_param}/merge_requests")
+        get api("/projects/#{project.id}/merge_requests")
         response.status.should == 401
       end
     end
 
     context "when authenticated" do
       it "should return an array of merge_requests" do
-        get api("/projects/#{project.to_param}/merge_requests", user)
+        get api("/projects/#{project.id}/merge_requests", user)
         response.status.should == 200
         json_response.should be_an Array
         json_response.first['title'].should == merge_request.title
@@ -31,13 +31,13 @@ describe API::API do
 
   describe "GET /projects/:id/merge_request/:merge_request_id" do
     it "should return merge_request" do
-      get api("/projects/#{project.to_param}/merge_request/#{merge_request.id}", user)
+      get api("/projects/#{project.id}/merge_request/#{merge_request.id}", user)
       response.status.should == 200
       json_response['title'].should == merge_request.title
     end
 
     it "should return a 404 error if merge_request_id not found" do
-      get api("/projects/#{project.to_param}/merge_request/999", user)
+      get api("/projects/#{project.id}/merge_request/999", user)
       response.status.should == 404
     end
   end
@@ -45,32 +45,32 @@ describe API::API do
   describe "POST /projects/:id/merge_requests" do
     context 'between branches projects' do
       it "should return merge_request" do
-        post api("/projects/#{project.to_param}/merge_requests", user),
+        post api("/projects/#{project.id}/merge_requests", user),
              title: 'Test merge_request', source_branch: "stable", target_branch: "master", author: user
         response.status.should == 201
         json_response['title'].should == 'Test merge_request'
       end
 
       it "should return 422 when source_branch equals target_branch" do
-        post api("/projects/#{project.to_param}/merge_requests", user),
+        post api("/projects/#{project.id}/merge_requests", user),
              title: "Test merge_request", source_branch: "master", target_branch: "master", author: user
         response.status.should == 422
       end
 
       it "should return 400 when source_branch is missing" do
-        post api("/projects/#{project.to_param}/merge_requests", user),
+        post api("/projects/#{project.id}/merge_requests", user),
              title: "Test merge_request", target_branch: "master", author: user
         response.status.should == 400
       end
 
       it "should return 400 when target_branch is missing" do
-        post api("/projects/#{project.to_param}/merge_requests", user),
+        post api("/projects/#{project.id}/merge_requests", user),
              title: "Test merge_request", source_branch: "stable", author: user
         response.status.should == 400
       end
 
       it "should return 400 when title is missing" do
-        post api("/projects/#{project.to_param}/merge_requests", user),
+        post api("/projects/#{project.id}/merge_requests", user),
              target_branch: 'master', source_branch: 'stable'
         response.status.should == 400
       end
@@ -90,54 +90,54 @@ describe API::API do
       end
 
       it "should return merge_request" do
-        post api("/projects/#{fork_project.to_param}/merge_requests", user2),
+        post api("/projects/#{fork_project.id}/merge_requests", user2),
              title: 'Test merge_request', source_branch: "stable", target_branch: "master", author: user2, target_project_id: project.id
         response.status.should == 201
         json_response['title'].should == 'Test merge_request'
       end
 
       it "should not return 422 when source_branch equals target_branch" do
-        project.to_param.should_not == fork_project.to_param
+        project.id.should_not == fork_project.id
         fork_project.forked?.should be_true
         fork_project.forked_from_project.should == project
-        post api("/projects/#{fork_project.to_param}/merge_requests", user2),
+        post api("/projects/#{fork_project.id}/merge_requests", user2),
              title: 'Test merge_request', source_branch: "master", target_branch: "master", author: user2, target_project_id: project.id
         response.status.should == 201
         json_response['title'].should == 'Test merge_request'
       end
 
       it "should return 400 when source_branch is missing" do
-        post api("/projects/#{fork_project.to_param}/merge_requests", user2),
+        post api("/projects/#{fork_project.id}/merge_requests", user2),
              title: 'Test merge_request', target_branch: "master", author: user2, target_project_id: project.id
         response.status.should == 400
       end
 
       it "should return 400 when target_branch is missing" do
-        post api("/projects/#{fork_project.to_param}/merge_requests", user2),
+        post api("/projects/#{fork_project.id}/merge_requests", user2),
              title: 'Test merge_request', target_branch: "master", author: user2, target_project_id: project.id
         response.status.should == 400
       end
 
       it "should return 400 when title is missing" do
-        post api("/projects/#{fork_project.to_param}/merge_requests", user2),
+        post api("/projects/#{fork_project.id}/merge_requests", user2),
              target_branch: 'master', source_branch: 'stable', author: user2, target_project_id: project.id
         response.status.should == 400
       end
 
       it "should return 400 when target_branch is specified and not a forked project" do
-        post api("/projects/#{project.to_param}/merge_requests", user),
+        post api("/projects/#{project.id}/merge_requests", user),
              title: 'Test merge_request', target_branch: 'master', source_branch: 'stable', author: user, target_project_id: fork_project.id
         response.status.should == 400
       end
 
       it "should return 400 when target_branch is specified and for a different fork" do
-        post api("/projects/#{fork_project.to_param}/merge_requests", user2),
+        post api("/projects/#{fork_project.id}/merge_requests", user2),
              title: 'Test merge_request', target_branch: 'master', source_branch: 'stable', author: user2, target_project_id: unrelated_project.id
         response.status.should == 400
       end
 
       it "should return 201 when target_branch is specified and for the same project" do
-        post api("/projects/#{fork_project.to_param}/merge_requests", user2),
+        post api("/projects/#{fork_project.id}/merge_requests", user2),
              title: 'Test merge_request', target_branch: 'master', source_branch: 'stable', author: user2, target_project_id: fork_project.id
         response.status.should == 201
       end
@@ -146,7 +146,7 @@ describe API::API do
 
   describe "PUT /projects/:id/merge_request/:merge_request_id to close MR" do
     it "should return merge_request" do
-      put api("/projects/#{project.to_param}/merge_request/#{merge_request.id}", user), state_event: "close"
+      put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), state_event: "close"
       response.status.should == 200
       json_response['state'].should == 'closed'
     end
@@ -154,7 +154,7 @@ describe API::API do
 
   describe "PUT /projects/:id/merge_request/:merge_request_id to merge MR" do
     it "should return merge_request" do
-      put api("/projects/#{project.to_param}/merge_request/#{merge_request.id}", user), state_event: "merge"
+      put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), state_event: "merge"
       response.status.should == 200
       json_response['state'].should == 'merged'
     end
@@ -162,19 +162,19 @@ describe API::API do
 
   describe "PUT /projects/:id/merge_request/:merge_request_id" do
     it "should return merge_request" do
-      put api("/projects/#{project.to_param}/merge_request/#{merge_request.id}", user), title: "New title"
+      put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), title: "New title"
       response.status.should == 200
       json_response['title'].should == 'New title'
     end
 
     it "should return 422 when source_branch and target_branch are renamed the same" do
-      put api("/projects/#{project.to_param}/merge_request/#{merge_request.id}", user),
+      put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user),
           source_branch: "master", target_branch: "master"
       response.status.should == 422
     end
 
     it "should return merge_request with renamed target_branch" do
-      put api("/projects/#{project.to_param}/merge_request/#{merge_request.id}", user), target_branch: "wiki"
+      put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), target_branch: "wiki"
       response.status.should == 200
       json_response['target_branch'].should == 'wiki'
     end
@@ -182,18 +182,18 @@ describe API::API do
 
   describe "POST /projects/:id/merge_request/:merge_request_id/comments" do
     it "should return comment" do
-      post api("/projects/#{project.to_param}/merge_request/#{merge_request.id}/comments", user), note: "My comment"
+      post api("/projects/#{project.id}/merge_request/#{merge_request.id}/comments", user), note: "My comment"
       response.status.should == 201
       json_response['note'].should == 'My comment'
     end
 
     it "should return 400 if note is missing" do
-      post api("/projects/#{project.to_param}/merge_request/#{merge_request.id}/comments", user)
+      post api("/projects/#{project.id}/merge_request/#{merge_request.id}/comments", user)
       response.status.should == 400
     end
 
     it "should return 404 if note is attached to non existent merge request" do
-      post api("/projects/#{project.to_param}/merge_request/111/comments", user), note: "My comment"
+      post api("/projects/#{project.id}/merge_request/111/comments", user), note: "My comment"
       response.status.should == 404
     end
   end
-- 
GitLab


From fa141971a38d8e1a46f497bc2b5d7457934b585b Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Mon, 16 Sep 2013 13:31:22 -0400
Subject: [PATCH 119/248] Make users theme configurable

GITLAB-1262

Change-Id: I690cb8ea294df53ebe8405a519c23c501af2c21a

Conflicts:
	app/models/user.rb
	config/initializers/1_settings.rb
	spec/models/user_spec.rb
---
 app/models/user.rb                |  2 +-
 config/gitlab.yml.example         |  8 ++++++++
 config/initializers/1_settings.rb |  1 +
 spec/models/user_spec.rb          | 21 ++++++++++++---------
 4 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/app/models/user.rb b/app/models/user.rb
index c1026a44f87..ea004e4c9a7 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -211,7 +211,7 @@ class User < ActiveRecord::Base
       {
         projects_limit: Gitlab.config.gitlab.default_projects_limit,
         can_create_group: Gitlab.config.gitlab.default_can_create_group,
-        theme_id: Gitlab::Theme::MARS
+        theme_id: Gitlab.config.gitlab.default_theme
       }
     end
   end
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index ffe333a1f8b..c847f1fdc8d 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -42,6 +42,14 @@ production: &base
     default_projects_limit: 10
     # default_can_create_group: false  # default: true
     # username_changing_enabled: false # default: true - User can change her username/namespace
+    ## Default theme
+    ##   BASIC  = 1
+    ##   MARS   = 2
+    ##   MODERN = 3
+    ##   GRAY   = 4
+    ##   COLOR  = 5
+    # default_theme: 1 # default: 1
+
 
     ## Users management
     # signup_enabled: true          # default: false - Account passwords are not sent via the email if signup is enabled.
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 1c528ef4907..41789ca56cd 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -52,6 +52,7 @@ Settings['issues_tracker']  ||= {}
 Settings['gitlab'] ||= Settingslogic.new({})
 Settings.gitlab['default_projects_limit'] ||= 10
 Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil?
+Settings.gitlab['default_theme'] = Gitlab::Theme::BASIC if Settings.gitlab['default_theme'].nil?
 Settings.gitlab['host']       ||= 'localhost'
 Settings.gitlab['https']        = false if Settings.gitlab['https'].nil?
 Settings.gitlab['port']       ||= Settings.gitlab.https ? 443 : 80
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 79915daa463..2b42226ecaf 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -221,9 +221,9 @@ describe User do
         let(:user) { User.build_user({}, as: :admin) }
 
         it "should apply defaults to user" do
-          user.projects_limit.should == 42
-          user.can_create_group.should be_false
-          user.theme_id.should == Gitlab::Theme::MARS
+          user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit
+          user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group
+          user.theme_id.should == Gitlab.config.gitlab.default_theme
         end
       end
 
@@ -231,6 +231,9 @@ describe User do
         let(:user) { User.build_user({projects_limit: 123, can_create_group: true, can_create_team: true, theme_id: Gitlab::Theme::BASIC}, as: :admin) }
 
         it "should apply defaults to user" do
+          Gitlab.config.gitlab.default_projects_limit.should_not == 123
+          Gitlab.config.gitlab.default_can_create_group.should_not be_true
+          Gitlab.config.gitlab.default_theme.should_not == Gitlab::Theme::MARS
           user.projects_limit.should == 123
           user.can_create_group.should be_true
           user.theme_id.should == Gitlab::Theme::BASIC
@@ -243,9 +246,9 @@ describe User do
         let(:user) { User.build_user }
 
         it "should apply defaults to user" do
-          user.projects_limit.should == 42
-          user.can_create_group.should be_false
-          user.theme_id.should == Gitlab::Theme::MARS
+          user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit
+          user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group
+          user.theme_id.should == Gitlab.config.gitlab.default_theme
         end
       end
 
@@ -253,9 +256,9 @@ describe User do
         let(:user) { User.build_user(projects_limit: 123, can_create_group: true, theme_id: Gitlab::Theme::BASIC) }
 
         it "should apply defaults to user" do
-          user.projects_limit.should == 42
-          user.can_create_group.should be_false
-          user.theme_id.should == Gitlab::Theme::MARS
+          user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit
+          user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group
+          user.theme_id.should == Gitlab.config.gitlab.default_theme
         end
       end
     end
-- 
GitLab


From 3ff48755c73ce49674655ed4332781077f70b933 Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Sun, 22 Sep 2013 01:06:22 -0400
Subject: [PATCH 120/248] Defaulted theme to MARS

Change-Id: I02814fb47edcc915309183547cc8dcb165100f4f
---
 config/gitlab.yml.example         | 2 +-
 config/initializers/1_settings.rb | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index c847f1fdc8d..073e76307a0 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -48,7 +48,7 @@ production: &base
     ##   MODERN = 3
     ##   GRAY   = 4
     ##   COLOR  = 5
-    # default_theme: 1 # default: 1
+    # default_theme: 2 # default: 2
 
 
     ## Users management
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 41789ca56cd..0ce8074f951 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -52,7 +52,7 @@ Settings['issues_tracker']  ||= {}
 Settings['gitlab'] ||= Settingslogic.new({})
 Settings.gitlab['default_projects_limit'] ||= 10
 Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil?
-Settings.gitlab['default_theme'] = Gitlab::Theme::BASIC if Settings.gitlab['default_theme'].nil?
+Settings.gitlab['default_theme'] = Gitlab::Theme::MARS if Settings.gitlab['default_theme'].nil?
 Settings.gitlab['host']       ||= 'localhost'
 Settings.gitlab['https']        = false if Settings.gitlab['https'].nil?
 Settings.gitlab['port']       ||= Settings.gitlab.https ? 443 : 80
-- 
GitLab


From 0689a94f9c6debadd6b38a5771cd7250d7241764 Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Sun, 22 Sep 2013 10:45:19 +0200
Subject: [PATCH 121/248] Version 6.1.0

---
 VERSION | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/VERSION b/VERSION
index 7c93db420c1..dfda3e0b4f0 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-6.1.0.rc1
+6.1.0
-- 
GitLab


From 8063037692ae46215f3c65f5e25dfa1f483ea495 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 22 Sep 2013 08:48:04 +0000
Subject: [PATCH 122/248] Fix hover for tree view

---
 app/assets/stylesheets/sections/tree.scss | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss
index ff31265bac1..3f163bc163c 100644
--- a/app/assets/stylesheets/sections/tree.scss
+++ b/app/assets/stylesheets/sections/tree.scss
@@ -65,7 +65,7 @@
     }
     td {
       line-height: 20px;
-      background: #fff !important;
+      background: #fff;
       border-left: none;
       border-right: none;
     }
@@ -125,4 +125,4 @@
 .tree-ref-holder {
   float: left;
   margin-top: 5px;
-}
+}
\ No newline at end of file
-- 
GitLab


From 8f05c167585f15b6832e0296fb20e47833eddf7e Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Thu, 12 Sep 2013 16:27:51 -0400
Subject: [PATCH 123/248] Allows username only updates to ldap properties

-when logging in if users are allowed to login with just usernames in ldap we will update uid of the user if their uid is out of date

Conflicts:
	spec/lib/auth_spec.rb

Change-Id: Ia171b3d5133da86edc18c0d08ecfaf6a174f2574
---
 lib/gitlab/ldap/user.rb     | 11 ++++-
 spec/lib/auth_oauth_spec.rb | 98 +++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+), 1 deletion(-)
 create mode 100644 spec/lib/auth_oauth_spec.rb

diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
index c8f3a69376a..1606210aafc 100644
--- a/lib/gitlab/ldap/user.rb
+++ b/lib/gitlab/ldap/user.rb
@@ -26,7 +26,7 @@ module Gitlab
             # * When user already has account and need to link his LDAP account.
             # * LDAP uid changed for user with same email and we need to update his uid
             #
-            user = model.find_by_email(email)
+            user = find_user(email)
 
             if user
               user.update_attributes(extern_uid: uid, provider: provider)
@@ -43,6 +43,15 @@ module Gitlab
           user
         end
 
+        def find_user(email)
+          if user = model.find_by_email(email)
+          elsif ldap_conf['allow_username_or_email_login']
+            uname = (email.partition('@').first) unless email.nil?
+            user = model.find_by_username(uname)
+          end
+          user
+        end
+
         def authenticate(login, password)
           # Check user against LDAP backend if user is not authenticated
           # Only check with valid login and password to prevent anonymous bind results
diff --git a/spec/lib/auth_oauth_spec.rb b/spec/lib/auth_oauth_spec.rb
new file mode 100644
index 00000000000..c9deb590f67
--- /dev/null
+++ b/spec/lib/auth_oauth_spec.rb
@@ -0,0 +1,98 @@
+require 'spec_helper'
+
+describe Gitlab::Auth do
+  let(:gl_auth) { Gitlab::Auth.new }
+
+  before do
+    Gitlab.config.stub(omniauth: {})
+
+    @info = mock(
+      uid: '12djsak321',
+      name: 'John',
+      email: 'john@mail.com'
+    )
+  end
+
+  describe :find_for_ldap_auth do
+    before do
+      @auth = mock(
+        uid: '12djsak321',
+        info: @info,
+        provider: 'ldap'
+      )
+    end
+
+    it "should find by uid & provider" do
+      User.should_receive :find_by_extern_uid_and_provider
+      gl_auth.find_for_ldap_auth(@auth)
+    end
+
+    it "should update credentials by email if missing uid" do
+      user = double('User')
+      User.stub find_by_extern_uid_and_provider: nil
+      User.stub find_by_email: user
+      user.should_receive :update_attributes
+      gl_auth.find_for_ldap_auth(@auth)
+    end
+
+    it "should update credentials by username if missing uid and Gitlab.config.ldap.allow_username_or_email_login is true" do
+      user = double('User')
+      value = Gitlab.config.ldap.allow_username_or_email_login
+      Gitlab.config.ldap['allow_username_or_email_login'] = true
+      User.stub find_by_extern_uid_and_provider: nil
+      User.stub find_by_email: nil
+      User.stub find_by_username: user
+      user.should_receive :update_attributes
+      gl_auth.find_for_ldap_auth(@auth)
+      Gitlab.config.ldap['allow_username_or_email_login'] = value
+    end
+
+    it "should not update credentials by username if missing uid and Gitlab.config.ldap.allow_username_or_email_login is false" do
+      user = double('User')
+      value = Gitlab.config.ldap.allow_username_or_email_login
+      Gitlab.config.ldap['allow_username_or_email_login'] = false
+      User.stub find_by_extern_uid_and_provider: nil
+      User.stub find_by_email: nil
+      User.stub find_by_username: user
+      user.should_not_receive :update_attributes
+      gl_auth.find_for_ldap_auth(@auth)
+      Gitlab.config.ldap['allow_username_or_email_login'] = value
+    end
+
+    it "should create from auth if user does not exist"do
+      User.stub find_by_extern_uid_and_provider: nil
+      User.stub find_by_email: nil
+      gl_auth.should_receive :create_from_omniauth
+      gl_auth.find_for_ldap_auth(@auth)
+    end
+  end
+
+  describe :find_or_new_for_omniauth do
+    before do
+      @auth = mock(
+        info: @info,
+        provider: 'twitter',
+        uid: '12djsak321',
+      )
+    end
+
+    it "should find user"do
+      User.should_receive :find_by_provider_and_extern_uid
+      gl_auth.should_not_receive :create_from_omniauth
+      gl_auth.find_or_new_for_omniauth(@auth)
+    end
+
+    it "should not create user"do
+      User.stub find_by_provider_and_extern_uid: nil
+      gl_auth.should_not_receive :create_from_omniauth
+      gl_auth.find_or_new_for_omniauth(@auth)
+    end
+
+    it "should create user if single_sing_on"do
+      Gitlab.config.omniauth['allow_single_sign_on'] = true
+      User.stub find_by_provider_and_extern_uid: nil
+      gl_auth.should_receive :create_from_omniauth
+      gl_auth.find_or_new_for_omniauth(@auth)
+    end
+  end
+end
-- 
GitLab


From 1142f152545b44aa66db3aa2d7498143d40b630a Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Mon, 16 Sep 2013 00:40:21 -0400
Subject: [PATCH 124/248] Added ldap tests

Change-Id: Ifd77615b3b92d7d8bca92b8875aa8204356cfd85
---
 .../ldap/ldap_user_auth_spec.rb}              | 51 ++-----------------
 1 file changed, 5 insertions(+), 46 deletions(-)
 rename spec/lib/{auth_oauth_spec.rb => gitlab/ldap/ldap_user_auth_spec.rb} (53%)

diff --git a/spec/lib/auth_oauth_spec.rb b/spec/lib/gitlab/ldap/ldap_user_auth_spec.rb
similarity index 53%
rename from spec/lib/auth_oauth_spec.rb
rename to spec/lib/gitlab/ldap/ldap_user_auth_spec.rb
index c9deb590f67..b1c583c0476 100644
--- a/spec/lib/auth_oauth_spec.rb
+++ b/spec/lib/gitlab/ldap/ldap_user_auth_spec.rb
@@ -1,7 +1,7 @@
 require 'spec_helper'
 
-describe Gitlab::Auth do
-  let(:gl_auth) { Gitlab::Auth.new }
+describe Gitlab::LDAP do
+  let(:gl_auth) { Gitlab::LDAP::User }
 
   before do
     Gitlab.config.stub(omniauth: {})
@@ -22,17 +22,12 @@ describe Gitlab::Auth do
       )
     end
 
-    it "should find by uid & provider" do
-      User.should_receive :find_by_extern_uid_and_provider
-      gl_auth.find_for_ldap_auth(@auth)
-    end
-
     it "should update credentials by email if missing uid" do
       user = double('User')
       User.stub find_by_extern_uid_and_provider: nil
       User.stub find_by_email: user
       user.should_receive :update_attributes
-      gl_auth.find_for_ldap_auth(@auth)
+      gl_auth.find_or_create(@auth)
     end
 
     it "should update credentials by username if missing uid and Gitlab.config.ldap.allow_username_or_email_login is true" do
@@ -43,7 +38,7 @@ describe Gitlab::Auth do
       User.stub find_by_email: nil
       User.stub find_by_username: user
       user.should_receive :update_attributes
-      gl_auth.find_for_ldap_auth(@auth)
+      gl_auth.find_or_create(@auth)
       Gitlab.config.ldap['allow_username_or_email_login'] = value
     end
 
@@ -55,44 +50,8 @@ describe Gitlab::Auth do
       User.stub find_by_email: nil
       User.stub find_by_username: user
       user.should_not_receive :update_attributes
-      gl_auth.find_for_ldap_auth(@auth)
+      gl_auth.find_or_create(@auth)
       Gitlab.config.ldap['allow_username_or_email_login'] = value
     end
-
-    it "should create from auth if user does not exist"do
-      User.stub find_by_extern_uid_and_provider: nil
-      User.stub find_by_email: nil
-      gl_auth.should_receive :create_from_omniauth
-      gl_auth.find_for_ldap_auth(@auth)
-    end
-  end
-
-  describe :find_or_new_for_omniauth do
-    before do
-      @auth = mock(
-        info: @info,
-        provider: 'twitter',
-        uid: '12djsak321',
-      )
-    end
-
-    it "should find user"do
-      User.should_receive :find_by_provider_and_extern_uid
-      gl_auth.should_not_receive :create_from_omniauth
-      gl_auth.find_or_new_for_omniauth(@auth)
-    end
-
-    it "should not create user"do
-      User.stub find_by_provider_and_extern_uid: nil
-      gl_auth.should_not_receive :create_from_omniauth
-      gl_auth.find_or_new_for_omniauth(@auth)
-    end
-
-    it "should create user if single_sing_on"do
-      Gitlab.config.omniauth['allow_single_sign_on'] = true
-      User.stub find_by_provider_and_extern_uid: nil
-      gl_auth.should_receive :create_from_omniauth
-      gl_auth.find_or_new_for_omniauth(@auth)
-    end
   end
 end
-- 
GitLab


From afd97d76d9006ac5fca79265fad410a072269c67 Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Sun, 22 Sep 2013 20:25:10 -0400
Subject: [PATCH 125/248] Update for readability

fixed a test a broke in the configurable theme PR
Change-Id: Id894506941bc01ab0d259d48ca7ff9b80bb2c57e
---
 lib/gitlab/ldap/user.rb  | 10 +++++++---
 spec/models/user_spec.rb |  2 +-
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
index 1606210aafc..260bacfeeb0 100644
--- a/lib/gitlab/ldap/user.rb
+++ b/lib/gitlab/ldap/user.rb
@@ -44,11 +44,15 @@ module Gitlab
         end
 
         def find_user(email)
-          if user = model.find_by_email(email)
-          elsif ldap_conf['allow_username_or_email_login']
-            uname = (email.partition('@').first) unless email.nil?
+          user = model.find_by_email(email)
+
+          # If no user found and allow_username_or_email_login is true
+          # we look for user by extracting part of his email
+          if !user && email && ldap_conf['allow_username_or_email_login']
+            uname = email.partition('@').first
             user = model.find_by_username(uname)
           end
+
           user
         end
 
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 2b42226ecaf..c879900f8fd 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -233,7 +233,7 @@ describe User do
         it "should apply defaults to user" do
           Gitlab.config.gitlab.default_projects_limit.should_not == 123
           Gitlab.config.gitlab.default_can_create_group.should_not be_true
-          Gitlab.config.gitlab.default_theme.should_not == Gitlab::Theme::MARS
+          Gitlab.config.gitlab.default_theme.should_not == Gitlab::Theme::BASIC
           user.projects_limit.should == 123
           user.can_create_group.should be_true
           user.theme_id.should == Gitlab::Theme::BASIC
-- 
GitLab


From e4370f52ce404a5c6d309103d498c2dab59fc9ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20Ko=CC=88nig?= <t.koenig@wollzelle.com>
Date: Mon, 23 Sep 2013 18:41:26 +0200
Subject: [PATCH 126/248] Sort active milestones by due dates (closest first)

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

diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb
index 39cd579cce5..3e88656cdf1 100644
--- a/app/controllers/projects/milestones_controller.rb
+++ b/app/controllers/projects/milestones_controller.rb
@@ -14,7 +14,7 @@ class Projects::MilestonesController < Projects::ApplicationController
     @milestones = case params[:f]
                   when 'all'; @project.milestones.order("state, due_date DESC")
                   when 'closed'; @project.milestones.closed.order("due_date DESC")
-                  else @project.milestones.active.order("due_date DESC")
+                  else @project.milestones.active.order("due_date ASC")
                   end
 
     @milestones = @milestones.includes(:project)
-- 
GitLab


From 465cdd9d98a85ce7067bb2263c085e704c520120 Mon Sep 17 00:00:00 2001
From: Sergio Pieiga <sergio.pieiga@gmail.com>
Date: Mon, 23 Sep 2013 14:09:29 -0400
Subject: [PATCH 127/248] Step 8, cd into /home/git/gitlab

need to be in /home/git/gitlab
---
 doc/update/6.0-to-6.1.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/doc/update/6.0-to-6.1.md b/doc/update/6.0-to-6.1.md
index 2fb762e467a..9ec99af205b 100644
--- a/doc/update/6.0-to-6.1.md
+++ b/doc/update/6.0-to-6.1.md
@@ -80,6 +80,7 @@ sudo chmod +x /etc/init.d/gitlab
 
 Check if GitLab and its environment are configured correctly:
 
+    cd /home/git/gitlab
     sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
 
 To make sure you didn't miss anything run a more thorough check with:
-- 
GitLab


From 5d9af70a98f5344a1e5611be2d7280c08ffa04bc Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Sun, 22 Sep 2013 00:50:18 -0400
Subject: [PATCH 128/248] Added search for projects by name to api

GITLAB-1283 (GITLAB-869)

Change-Id: I611e7e93f6292de08e1edc8d3ea77cf9087b6ded

Conflicts:
	config/initializers/1_settings.rb
---
 app/contexts/search_context.rb     |  2 +-
 lib/api/projects.rb                | 53 +++++++++++++++++++-----------
 spec/requests/api/projects_spec.rb | 38 +++++++++++++++++++++
 3 files changed, 73 insertions(+), 20 deletions(-)

diff --git a/app/contexts/search_context.rb b/app/contexts/search_context.rb
index 0817d52cd00..48def0784fd 100644
--- a/app/contexts/search_context.rb
+++ b/app/contexts/search_context.rb
@@ -13,7 +13,7 @@ class SearchContext
     projects = Project.where(id: project_ids)
     result[:projects] = projects.search(query).limit(20)
 
-    # Search inside singe project
+    # Search inside single project
     project = projects.first if projects.length == 1
 
     if params[:search_code].present?
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index c6ff524cb06..d17b791dccc 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -73,16 +73,16 @@ module API
       post do
         required_attributes! [:name]
         attrs = attributes_for_keys [:name,
-                                    :path,
-                                    :description,
-                                    :default_branch,
-                                    :issues_enabled,
-                                    :wall_enabled,
-                                    :merge_requests_enabled,
-                                    :wiki_enabled,
-                                    :snippets_enabled,
-                                    :namespace_id,
-                                    :public]
+                                     :path,
+                                     :description,
+                                     :default_branch,
+                                     :issues_enabled,
+                                     :wall_enabled,
+                                     :merge_requests_enabled,
+                                     :wiki_enabled,
+                                     :snippets_enabled,
+                                     :namespace_id,
+                                     :public]
         @project = ::Projects::CreateContext.new(current_user, attrs).execute
         if @project.saved?
           present @project, with: Entities::Project
@@ -113,14 +113,14 @@ module API
         authenticated_as_admin!
         user = User.find(params[:user_id])
         attrs = attributes_for_keys [:name,
-                                    :description,
-                                    :default_branch,
-                                    :issues_enabled,
-                                    :wall_enabled,
-                                    :merge_requests_enabled,
-                                    :wiki_enabled,
-                                    :snippets_enabled,
-                                    :public]
+                                     :description,
+                                     :default_branch,
+                                     :issues_enabled,
+                                     :wall_enabled,
+                                     :merge_requests_enabled,
+                                     :wiki_enabled,
+                                     :snippets_enabled,
+                                     :public]
         @project = ::Projects::CreateContext.new(user, attrs).execute
         if @project.saved?
           present @project, with: Entities::Project
@@ -165,7 +165,6 @@ module API
         end
       end
 
-
       # Get a project team members
       #
       # Parameters:
@@ -262,6 +261,22 @@ module API
           {message: "Access revoked", id: params[:user_id].to_i}
         end
       end
+
+      # search for projects current_user has access to
+      #
+      # Parameters:
+      #   query (required) - A string contained in the project name
+      #   per_page (optional) - number of projects to return per page, defaults to 20
+      #   offset (optional) - the offset in pages to retrieve
+      # Example Request:
+      #   GET /projects/search/:query
+      get "/search/:query" do
+        limit = (params[:per_page] || 20).to_i
+        offset = (params[:page] || 0).to_i * limit
+        ids = current_user.authorized_projects.map(&:id)
+        projects = Project.where("(id in (?) OR public = true) AND (name LIKE (?))", ids, "%#{params[:query]}%").limit(limit).offset(offset)
+        present projects, with: Entities::Project
+      end
     end
   end
 end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 2de3dc55e40..b8c0b6f33ed 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -692,4 +692,42 @@ describe API::API do
       end
     end
   end
+
+  describe "GET /projects/search/:query" do
+    let!(:query) { 'query'}
+    let!(:search) { create(:project, name: query, creator_id: user.id, namespace: user.namespace) }
+    let!(:pre) { create(:project, name: "pre_#{query}", creator_id: user.id, namespace: user.namespace) }
+    let!(:post) { create(:project, name: "#{query}_post", creator_id: user.id, namespace: user.namespace) }
+    let!(:pre_post) { create(:project, name: "pre_#{query}_post", creator_id: user.id, namespace: user.namespace) }
+    let!(:unfound) { create(:project, name: 'unfound', creator_id: user.id, namespace: user.namespace) }
+    let!(:public) { create(:project, name: "another #{query}",public: true) }
+    let!(:unfound_public) { create(:project, name: 'unfound public', public: true) }
+
+    context "when unauthenticated" do
+      it "should return authentication error" do
+        get api("/projects/search/#{query}")
+        response.status.should == 401
+      end
+    end
+
+    context "when authenticated" do
+      it "should return an array of projects" do
+        get api("/projects/search/#{query}",user)
+        response.status.should == 200
+        json_response.should be_an Array
+        json_response.size.should == 5
+        json_response.each {|project| project['name'].should =~ /.*query.*/}
+      end
+    end
+
+    context "when authenticated as a different user" do
+      it "should return matching public projects" do
+        get api("/projects/search/#{query}", user2)
+        response.status.should == 200
+        json_response.should be_an Array
+        json_response.size.should == 1
+        json_response.first['name'].should == "another #{query}"
+      end
+    end
+  end
 end
-- 
GitLab


From 49fc43bfb1febf3207598fb1d9b4b8cd599a02fd Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Mon, 23 Sep 2013 19:18:29 -0400
Subject: [PATCH 129/248] Added missing API documentation

Change-Id: I1337ee7ff51d018d6f62d447345032597e84269f
---
 doc/api/projects.md | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/doc/api/projects.md b/doc/api/projects.md
index 9afffcbaa80..380f6f21ce8 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -484,3 +484,18 @@ DELETE /projects/:id/fork
 Parameter:
 
 + `id` (required) - The ID of the project
+
+
+## Search for projects by name
+
+Search for projects by name which are public or the calling user has access to
+
+```
+GET /projects/search/:query
+```
+
+Parameters:
+
++   query (required) - A string contained in the project name
++   per_page (optional) - number of projects to return per page, defaults to 20
++   offset (optional) - the offset in pages to retrieve
-- 
GitLab


From 20ddb96420c58d41ace05cb036ac33b4a2860813 Mon Sep 17 00:00:00 2001
From: Hiroyuki Sato <sathiroyuki@gmail.com>
Date: Tue, 24 Sep 2013 15:31:12 +0900
Subject: [PATCH 130/248] Update check script

* GitLab Shell 1.7.1 is required
* Global projects are not supported (refs #5152)
---
 lib/tasks/gitlab/check.rake | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 1e9228a3509..c445c0fbddd 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -22,6 +22,7 @@ namespace :gitlab do
       check_tmp_writable
       check_init_script_exists
       check_init_script_up_to_date
+      check_projects_have_namespace
       check_satellites_exist
       check_redis_version
       check_git_version
@@ -552,6 +553,32 @@ namespace :gitlab do
       end
     end
 
+    def check_projects_have_namespace
+      print "projects have namespace: ... "
+
+      unless Project.count > 0
+        puts "can't check, you have no projects".magenta
+        return
+      end
+      puts ""
+
+      Project.find_each(batch_size: 100) do |project|
+        print "#{project.name_with_namespace.yellow} ... "
+
+        if project.namespace
+          puts "yes".green
+        else
+          puts "no".red
+          try_fixing_it(
+            "Migrate global projects"
+          )
+          for_more_information(
+            "doc/update/5.4-to-6.0.md in section \"#global-projects\""
+          )
+          fix_and_rerun
+        end
+      end
+    end
 
     # Helper methods
     ########################
@@ -659,7 +686,7 @@ namespace :gitlab do
   end
 
   def check_gitlab_shell
-    required_version = Gitlab::VersionInfo.new(1, 7, 0)
+    required_version = Gitlab::VersionInfo.new(1, 7, 1)
     current_version = Gitlab::VersionInfo.parse(gitlab_shell_version)
 
     print "GitLab Shell version >= #{required_version} ? ... "
-- 
GitLab


From 1328e8f66440ddd975a0f2b82ca74ac4fa5f8d33 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 24 Sep 2013 10:48:36 +0300
Subject: [PATCH 131/248] Force user to provide old password in order to change
 it

---
 app/controllers/profiles_controller.rb |  9 +++++-
 app/views/profiles/account.html.haml   | 45 +++++++++++++++-----------
 features/profile/profile.feature       |  6 ++++
 features/steps/profile/profile.rb      | 18 +++++++++++
 4 files changed, 59 insertions(+), 19 deletions(-)

diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index 6fa635d0e36..780f47d9960 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -33,7 +33,14 @@ class ProfilesController < ApplicationController
   end
 
   def update_password
-    params[:user].reject!{ |k, v| k != "password" && k != "password_confirmation"}
+    params[:user].select! do |key, value|
+      %w(current_password password password_confirmation).include?(key.to_s)
+    end
+
+    unless @user.valid_password?(params[:user][:current_password])
+      redirect_to account_profile_path, alert: 'You must provide a valid current password'
+      return
+    end
 
     if @user.update_attributes(params[:user])
       flash[:notice] = "Password was successfully updated. Please login with it"
diff --git a/app/views/profiles/account.html.haml b/app/views/profiles/account.html.haml
index 8f43db66249..42c7ec051cb 100644
--- a/app/views/profiles/account.html.haml
+++ b/app/views/profiles/account.html.haml
@@ -57,24 +57,33 @@
       .tab-pane#tab-password
         %fieldset.update-password
           %legend Password
-          = form_for @user, url: update_password_profile_path, method: :put do |f|
-            %div
-              %p.slead After a successful password update you will be redirected to login page where you should login with your new password
-              -if @user.errors.any?
-                .alert.alert-error
-                  %ul
-                    - @user.errors.full_messages.each do |msg|
-                      %li= msg
-              .control-group
-                = f.label :password
-                .controls= f.password_field :password, required: true
-              .control-group
-                = f.label :password_confirmation
-                .controls
-                  = f.password_field :password_confirmation, required: true
-              .control-group
-                .controls
-                  = f.submit 'Save password', class: "btn btn-save"
+          - if current_user.ldap_user?
+            %h3.nothing_here_message Not available for LDAP user
+          - else
+            = form_for @user, url: update_password_profile_path, method: :put do |f|
+              %div
+                %p.slead
+                  You must provide current password in order to change it.
+                  %br
+                  After a successful password update you will be redirected to login page where you should login with your new password
+                -if @user.errors.any?
+                  .alert.alert-error
+                    %ul
+                      - @user.errors.full_messages.each do |msg|
+                        %li= msg
+                .control-group
+                  = f.label :current_password, class: 'cgreen'
+                  .controls= f.password_field :current_password, required: true
+                .control-group
+                  = f.label :password, 'New password'
+                  .controls= f.password_field :password, required: true
+                .control-group
+                  = f.label :password_confirmation
+                  .controls
+                    = f.password_field :password_confirmation, required: true
+                .control-group
+                  .controls
+                    = f.submit 'Save password', class: "btn btn-save"
 
       - if show_profile_social_tab?
         .tab-pane#tab-social
diff --git a/features/profile/profile.feature b/features/profile/profile.feature
index 3b61552a73d..c74b0993fb3 100644
--- a/features/profile/profile.feature
+++ b/features/profile/profile.feature
@@ -11,6 +11,12 @@ Feature: Profile
     Then I change my contact info
     And I should see new contact info
 
+  Scenario: I change my password without old one
+    Given I visit profile account page
+    When I try change my password w/o old one
+    Then I should see a missing password error message
+    And I should be redirected to account page
+
   Scenario: I change my password
     Given I visit profile account page
     Then I change my password
diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb
index 6944977c3ff..5b2a6321265 100644
--- a/features/steps/profile/profile.rb
+++ b/features/steps/profile/profile.rb
@@ -22,8 +22,17 @@ class Profile < Spinach::FeatureSteps
     @user.twitter.should == 'testtwitter'
   end
 
+  step 'I try change my password w/o old one' do
+    within '.update-password' do
+      fill_in "user_password", with: "222333"
+      fill_in "user_password_confirmation", with: "222333"
+      click_button "Save"
+    end
+  end
+
   step 'I change my password' do
     within '.update-password' do
+      fill_in "user_current_password", with: "123456"
       fill_in "user_password", with: "222333"
       fill_in "user_password_confirmation", with: "222333"
       click_button "Save"
@@ -32,12 +41,17 @@ class Profile < Spinach::FeatureSteps
 
   step 'I unsuccessfully change my password' do
     within '.update-password' do
+      fill_in "user_current_password", with: "123456"
       fill_in "user_password", with: "password"
       fill_in "user_password_confirmation", with: "confirmation"
       click_button "Save"
     end
   end
 
+  step "I should see a missing password error message" do
+    page.should have_content "You must provide a valid current password"
+  end
+
   step "I should see a password error message" do
     page.should have_content "Password doesn't match confirmation"
   end
@@ -110,6 +124,10 @@ class Profile < Spinach::FeatureSteps
     current_path.should == new_user_session_path
   end
 
+  step 'I should be redirected to account page' do
+    current_path.should == account_profile_path
+  end
+
   step 'I click on my profile picture' do
     click_link 'profile-pic'
   end
-- 
GitLab


From 8d90c148763de160e8fd2238756bf34220a1e4e9 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 24 Sep 2013 12:08:28 +0300
Subject: [PATCH 132/248] Dont override default table with bootstrap class.
 Refactor table css

---
 app/assets/stylesheets/gitlab_bootstrap.scss  |  1 -
 .../stylesheets/gitlab_bootstrap/files.scss   |  4 ++
 .../stylesheets/gitlab_bootstrap/mixins.scss  |  8 +++
 .../stylesheets/gitlab_bootstrap/tables.scss  | 68 -------------------
 app/assets/stylesheets/sections/tree.scss     | 42 +++++-------
 app/views/projects/tree/_tree.html.haml       |  2 +-
 app/views/projects/tree/_tree_item.html.haml  |  2 +-
 7 files changed, 31 insertions(+), 96 deletions(-)
 delete mode 100644 app/assets/stylesheets/gitlab_bootstrap/tables.scss

diff --git a/app/assets/stylesheets/gitlab_bootstrap.scss b/app/assets/stylesheets/gitlab_bootstrap.scss
index 1b24683fd97..faf36b702c0 100644
--- a/app/assets/stylesheets/gitlab_bootstrap.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap.scss
@@ -62,6 +62,5 @@ $baseLineHeight: 18px !default;
 @import "gitlab_bootstrap/buttons.scss";
 @import "gitlab_bootstrap/blocks.scss";
 @import "gitlab_bootstrap/files.scss";
-@import "gitlab_bootstrap/tables.scss";
 @import "gitlab_bootstrap/lists.scss";
 @import "gitlab_bootstrap/forms.scss";
diff --git a/app/assets/stylesheets/gitlab_bootstrap/files.scss b/app/assets/stylesheets/gitlab_bootstrap/files.scss
index a0d6682eb8f..8ba8c93e3d6 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/files.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/files.scss
@@ -6,6 +6,10 @@
   border: 1px solid #CCC;
   margin-bottom: 1em;
 
+  table {
+    @extend .table;
+  }
+
   .file-title {
     border-bottom: 1px solid #bbb;
     @include bg-dark-gray-gradient;
diff --git a/app/assets/stylesheets/gitlab_bootstrap/mixins.scss b/app/assets/stylesheets/gitlab_bootstrap/mixins.scss
index e7daf8f43b4..8b975a12cf7 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/mixins.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/mixins.scss
@@ -95,6 +95,14 @@
     font-size: 14px;
     line-height: 1.5;
   }
+
+  table {
+    @extend .table;
+    @extend .table-bordered;
+    th {
+      background: #EEE;
+    }
+  }
 }
 
 @mixin page-title {
diff --git a/app/assets/stylesheets/gitlab_bootstrap/tables.scss b/app/assets/stylesheets/gitlab_bootstrap/tables.scss
deleted file mode 100644
index 29ec1b584bd..00000000000
--- a/app/assets/stylesheets/gitlab_bootstrap/tables.scss
+++ /dev/null
@@ -1,68 +0,0 @@
-table {
-  @extend .table;
-  @extend .table-striped;
-  border: 1px solid #CCC;
-  width: 100%;
-
-  &.low {
-    td {
-      line-height: 18px;
-    }
-  }
-
-  &.headless {
-    tr:first-child td{
-      border-top: 1px solid #CCC;
-    }
-  }
-
-  th {
-    font-weight: normal;
-    font-size: 15px;
-    vertical-align: middle;
-    border-bottom: 1px solid #CCC;
-    text-shadow: 0 1px 1px #fff;
-
-    ul.nav {
-      text-shadow: none;
-      margin: 0;
-    }
-  }
-
-  th, td {
-    padding: 10px;
-    line-height: 18px;
-    text-align: left;
-  }
-
-  td {
-    border-color: #f1f1f1;
-    line-height: 28px;
-
-    .s16 {
-      margin-top: 5px;
-      margin-right: 5px;
-    }
-
-    &:first-child {
-      border-left: 1px solid #CCC;
-    }
-
-    &:last-child {
-      border-right: 1px solid #CCC;
-    }
-  }
-
-  &.bordered {
-    @extend .table-bordered;
-  }
-
-  &.lite {
-    border: none;
-    box-shadow: none;
-    tr, td {
-      border: none;
-      background:none !important;
-    }
-  }
-}
diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss
index 3f163bc163c..2a84741f0d6 100644
--- a/app/assets/stylesheets/sections/tree.scss
+++ b/app/assets/stylesheets/sections/tree.scss
@@ -13,13 +13,21 @@
   }
 
   .tree-table {
+    @extend .table;
     @include border-radius(0);
-    .tree-item {
-      td {
+
+    tr {
+      td, th {
         padding: 8px 10px;
-        strong {
-          font-weight: normal;
-        }
+        line-height: 20px;
+      }
+      th {
+        font-weight: normal;
+        font-size: 15px;
+        border-bottom: 1px solid #CCC;
+      }
+      td {
+        border-color: #F1F1F1;
       }
       &:hover {
         td {
@@ -29,12 +37,11 @@
         }
         cursor: pointer;
       }
-
       &.selected {
         td {
-          background: $hover;
-          border-top: 1px solid #ADF;
-          border-bottom: 1px solid #ADF;
+          background: #f5f5f5;
+          border-top: 1px solid #EEE;
+          border-bottom: 1px solid #EEE;
         }
       }
     }
@@ -56,21 +63,6 @@
     }
   }
 
-  .tree-table {
-    border: none;
-
-    th .btn {
-      margin: -2px -1px;
-      padding: 2px 10px;
-    }
-    td {
-      line-height: 20px;
-      background: #fff;
-      border-left: none;
-      border-right: none;
-    }
-  }
-
   .tree_author {
     padding-right: 8px;
 
@@ -125,4 +117,4 @@
 .tree-ref-holder {
   float: left;
   margin-top: 5px;
-}
\ No newline at end of file
+}
diff --git a/app/views/projects/tree/_tree.html.haml b/app/views/projects/tree/_tree.html.haml
index 0b1148b3e74..ae5f30c0004 100644
--- a/app/views/projects/tree/_tree.html.haml
+++ b/app/views/projects/tree/_tree.html.haml
@@ -26,7 +26,7 @@
             = link_to @commit.short_id, project_commit_path(@project, @commit)
             &ndash;
             = truncate(@commit.title, length: 50)
-        %th= link_to "history", project_commits_path(@project, @id), class: "btn btn-tiny pull-right"
+        %th= link_to "history", project_commits_path(@project, @id), class: "pull-right"
 
     - if tree.up_dir?
       %tr.tree-item
diff --git a/app/views/projects/tree/_tree_item.html.haml b/app/views/projects/tree/_tree_item.html.haml
index 0a76d5c21b6..f8856afc866 100644
--- a/app/views/projects/tree/_tree_item.html.haml
+++ b/app/views/projects/tree/_tree_item.html.haml
@@ -1,7 +1,7 @@
 %tr{ class: "tree-item #{tree_hex_class(tree_item)}" }
   %td.tree-item-file-name
     = tree_icon(type)
-    %strong= link_to truncate(tree_item.name, length: 40), project_tree_path(@project, tree_join(@id || @commit.id, tree_item.name))
+    %span= link_to truncate(tree_item.name, length: 40), project_tree_path(@project, tree_join(@id || @commit.id, tree_item.name))
   %td.tree_time_ago.cgray
     %span.log_loading.hide
       Loading commit data...
-- 
GitLab


From f5536c499a7350be9c4e732fdaf8738335576018 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 24 Sep 2013 12:27:25 +0300
Subject: [PATCH 133/248] Restyle sign-in page. Mention public projects

---
 app/assets/images/login-logo.png           | Bin 10209 -> 0 bytes
 app/assets/stylesheets/sections/login.scss |   5 +++--
 app/views/layouts/devise.html.haml         |   7 ++++++-
 3 files changed, 9 insertions(+), 3 deletions(-)
 delete mode 100644 app/assets/images/login-logo.png

diff --git a/app/assets/images/login-logo.png b/app/assets/images/login-logo.png
deleted file mode 100644
index a61c41303c4d6a13cfd9cbd762bff96820233299..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 10209
zcmaKSWl$Wz5+($f;IhEt8r&_oySu}pK^KSM1oz<X2@u@f7IzEo?(TYdCslV<ukOdl
z*F7^oX1cnkXTAs(CF#$|gvd}(P@iRGB-EgwpjrR*oe|;x)pNiYvVRS{nY^?Flr)qg
zly=VA-u6EUl9P<C3ltOz_J0aAR7MuypAf-SR#6gR4IT#(k664H5cf|+;3}!(D(+}+
zZ{gqyCGKot>S|$5=3(P%O(rd?sG=Q+h7Scr1|=&Ys^PhOmhF*csO@&qWt;0Vy88Y1
zq;;8hO__zR^Mx}4C|I!@8dV?@N;Y7(Lx7B&B`*F4`Y<h(m&p3Tv^WwCH-=nwOiT<4
z{AlA3i$A&@v6h@2Yu~NT1+6X~2KgQ)q8WAVBc+!&Car`>;(le-J~&o2+%MY>k2`w(
z?lG&;`9(e=^eL*}3~uZnC=bwO#EZgZ{V%xYljZ-T|F4))tNZ`V|DXE*jx89^m)ymr
zP;vhf(965*uIU+#b8VyDW1gIeK511k;W3yvie%uYR$Dey=RLt&YG|veX7spN)iEu|
z_*KUpim+@5w5LYKWG=S7K_%4tOZl^CrEVW{rK%7pn<-4CD@AMvm_MG~oWuviRB?HX
zhBn_1XwKCl8rw<?JP?E<uF(uuHMNgTO=wAw`c9+a8?;0gYt{{UJ#BAj7c_TyAWUGd
z{Mud9WIW$`w(!_V;|<*`h=E=Jd%7*S*sXf*Mt?}j+DFQ3SLJi-YWWxs`o;!`KDOjS
z%sHBm7)#I5T36Z#&d(*sh&;$$L7{&f%dDhMoqf(=dOG$o{gRLJZkkvy&K@cPI#f&a
z_Q8`YEL**Bj)m-+p$vO;5pabVX<^W_0o+c3<vrycAs3Aorh_1Km(3&l=A~KNC|&lt
zpcVfM#W98|79~W{E2=Yr*$(1|O(^M;ME&eN#S6m`tPdqlLenf<R8yS?)oT+T^a}^b
z0_Z{!iy40d%;z!DnU$3)9zidKH6i?p=+7tlsqy)ltNmlZgS;~sQ{9JI4##+%-E-iR
zB`a0ti07!GqZwEcdpRxfk)T=Ac8c)Im%=Dkn;pirvGH<J-<aaAkE7YpvHeNKT{Z*V
zcXOxcRf<z6$Rr?Z+STEWugm-1hU^=h-AIJD!SjTs&#V1MHkNcg6&if~v~{5>ML-@`
zzh((EzFM+Rfh*S<sZr0{pZ6$ZpEpxi>HT_UQQP3ctO6Y~sKQOy-rZ(2w28jvsT>uG
z!Bi<x5i-IEJQe~Nw;g-594fy#E7QAiUI`5C_~`{x6JrR)H8nc+aL!W^He3O4HL?Bg
z02?}YkDCRq%o}56yUFM0agXaMN52V}jSt*u=(o^xJRXC$-$mAaU|c1@HaEQUlhF1F
z4<@m|_dW(4@89G<3HO;u4f}F8?l6BUeNw=wfY~Bc#S*nO#Hk93vS1Bo)4<+4mv^+<
zGj0#w(v7%ENtnfgY%ALmTj$RMr2N;S-!8!KwSFDK{=gGRZo&I$8R3YnA}dw{$&CQ&
zW$BQe+UEqYH`9K}Z%Zk`hXj8P=?-j=f^`D{hBZ#=uWRpf&so9Ob=nPa$m%W;gfKmE
ze><5uw#0;dfd(Kva4F``Anbe9U&jp3{RYce(0uo%?R4=smyCI@Py!`Mt&m3KpA|Pq
zqRN#zl@NZbA06DU+S`xY2o_#RU&hb>)bm#_Sgprg3z>kruK@AGP%J{oB|Z6zU-n;3
zF}G4A4Q=zWPh@77X2n!^F<m0CldYE}ZY9}UpQKr@P(HM(kx`bbVtVpQQ|bJhx24vf
z2QT_EIqoPLcb^IIBoDS;LTtGK6`0gM?kCDJBucu_ncwi%4Mtxa9<jGu1q>`)Rhy&d
z=~U^!Q;69=e`znP0+Q(J(G124GAUGk6AQ7Q$esIbWP3&+p*f61NGOmO<W)PzV)9@s
z@TyiZ2vj11r3ZGLX=p=r>mvC*;LM<k2M|#ZpTgxYRzt9F7hq5nBE&+X#I{OdQF4Fm
zSne9vvjOZesCy0u_I`#e)a|dIL=^v;NWR?$pEtjPB*w-}h^OF-VWX>8fHc={R=h;%
zT5Q$%894rzohWp)L1;~jNotQdacYsGY_IIIu}h7_d;;Alz#;=QXK;VWm{Eq6!=An>
zO(dqeK}fP%l64rLd{y4*@|`)!`d8Bh$7{5udS&HK{20E_0063f1TDVm_B>hWr5+r0
z-W%fsIx3g}>-|<$)LYf{3C2$LAdUG&VXv-00vppQi_D}_<I&&~xKy3`Rd-2DXmWI?
zErkvmH1w2V*n%3dC4d`%)-Ue~4feo@(!`Eh4N4mk0VtS2W5*I#e0I~j(q`Bgd8yJH
zyreu+zXoQm&kRIf>-MC%YXZ>G1Y%h_uH6*m({Zay_fuX3CgR?k3RdV$v&;b21m|XJ
z&sLAupvi>AR(x7vXItgEsN;R1d4mVrb@!XIF?vH3Udd5K*!dI<N^Qdd{M;3Y%4FXn
z%~K<l@!Q6vN-x9UIuZvw_DY`{sUC#bMHo&(rKF(lp(<GUrrTJsr`7s4O_+t^c58O#
zZ{SHf&ySG1RtJN=-=#IV;fW~aR>iFOPZpfv?0_?jKNV67=y}U>gJ3Q;#K>$v7XP<J
zbXkGAFlUZs<duk>dyJ^(J}mu`OayI%#&~MQ3yK0@($0@c-^;T|SjW~qOA?>!%(VQW
zA|Yv(eelC^L(wX%9A6IyRrNfn2`OY_sefst9<zE&Qpiys?AR<7D<PMpW;fJ$#UlJd
zvP9Y;W1|%7rEeHE;&t1WZMS~U^?pd1U0&9Vmk(|HLbn$HmSr>y>3T%+JRj;?l~~`}
ztaQkGc}!fEt)=Qf5GSFoVWq*Ancg?RFGfJC*^w~qwYgTxHvdwm#*@gJEJJ6crlTR&
zq?^R5p{~@}5^BD3`KW7xrSs)&cc`A!+-X5*U|9)G1>3I^B`1tFcM-yLQM%=;y&j3f
z0}Kk+UF{}znK-!eDt5Ie&M-K!9al&hYeyhAT1CYC5q)*E@yz%g-OH*XKrs`r$n~eP
zfX_>pEuNm9_4b7dQf2hY2P13{Hk`e<Z>@WA`O$gB`#p3SBZ0NVQ3RDikt4OjMr82U
zd5C-;ZNav5zu6}&dS|WAo!0hABLi|tyr4eY==`G344^v$b)oNO5;&r(bk9^N*RE~*
z!kyP-lfb8&?s1LC>948DoHeeJXGKEd!Z}udpET!a=^=*qn6?J;=uBNpXyVJriyGU>
zyEZw7;t|cD0wD@9<w^4UcV`G7^-2P`9KUyz+9e*^kuL#=M!NpZp2|2VpR902oT>i$
zd|T9bPu9ToRV;s|zqx4MTcOd%t0<c9PBuE@IRYSye)B|%5S2SEBvw8A2_93@-QsVN
zk+P%(uI)ryL`h_9-#rHVqtC^qgI`nOn;jANta5h&t~lpH6PcNmmJJM_fZtSW2+Yfh
zk|GIv#`p?7U?>?5h6RVs9yOQQu)kafYt&q!Gkq>yuO4ar&%JLF>~MJqAUAxoh55xw
z`zOP9P_x)GIL=-mATN@wu6N*mqO~QlY3$2*v_;35Juo8qn=o$y9;ER4uYDQ>#_A4`
zf%i$vXhuSD_;a8>F8p^%SOmJY4cU5Ozi$qNz1@MFZ!prI5ENl0RFElt1sd#BYo<mt
zmhGTvMmgjgFtg~T5b~bh&7NJrpW%jxMn#qBhU2sNgA@oWyvjauF{rncilih=qw|#&
z*SYvBAtN_cCQ`0S@%7(OV+%20US^2}8r{COlso>5-{bc(pOJp^4Q*f%xZO|Da(jB4
zaU}Ug+~10${(1ob0Olqp@$c`V0?M-n$#uvaJ$=|V`<06rq0gW26{0Q`F1$%D-r=R%
zyA?T9A|VJnZsl|_9j2B32l@KaGzrLk@)CfIKHnOhLP(hfgHsXEeD`*kHDjakEZ^6b
zp<u6^M0(Z?U#%2axf{g{CkZ{v%kQt(Rrle<*Yzk$G%4L_JT`;{JE(f<`xkjkA~8}@
zM_rT08Gzk0oe|lw)}CSC-PYT~Mo8I1{`9Va)DeR@<`8pOYV6@+m<+1${t}%(40=DN
z$D3o6+RB@zgX?rWT+lUIy2cWho}tUC^9Cvw3b1l`*JnLJ0mCo1IhaJEG!ws=Si665
z+3RFoQo9s{<PF!nI}t6#@;=EE7esEVbOu@%B+X>d@M{j*j>0NJdwYJX=<%^giDJoB
zgxl-)%tuo$Fn>XF+Vmh&&2gEJqtxG;WT)mdT8y!kg9^T|Ny376OJOp!cXjnmCHdg#
zVI#o?{&H|1<?X6P)9zpkE$3E0$ru-Q#MK`6XE`*V4#LH$pqZ3@uq${d9^+$+{dblB
z)tAxfY^0(fpCkqpO^Uze;?VoPG)++G##&D&)}??n$JwV^yr1RoZ8Qd&j!EV$(Tk=K
zXduYSiP?iM(fg1WnTW75g&Si(dSn~Fo*{(`JgEML2+tq(Z0-2qq&EUMr5A-&01QnQ
z9+u|>rZVy!<QhxvU|bj^Bcdfo!Ae&luAapZ>s$MmJ!E;|{mTpzSxit`>6Gt&xQm;D
z;Qd&eQ&YyE5?qrgebG1N`G=+u%m((BXW%o`xuqSi8no3N&mlab{W{pppAg1bH*`Nx
z-&J=1_evAJx@d*yU#%-d^V;o&6I`8QoqQ(?QI8Z3od|(}86#?HZfq0BbJy5>8=78~
zhTtzF1p09j5{IO#gE@oTpH$R@BzDI9_9v@ATdys1<GGOTQ>jn}EUUjaPG_#Q3fwoA
z?Wt;3ekz%YNTOiOxZ^h)ila@Lv3cUu_%3ENaLAQUG`lMwrni-b$z1-IjR*mwA2tQW
zZu{GGH@1cSGn)k(@ml7a2@ri9BhsBneFv-ab|Xt3vEB|$?QeY6sKyHfDUA(3z1+UW
zIjl>(?`88o9d)SN{M+kNYiV^s{hc3N<5Y}v%?qwqItMa>;bZ%#!F-A>C;0~W^`>Z=
z<)x)NrXC#LkuEWsyA1^A0}6IXlogx|%&o};7We`AI)=^h!R{8b{p}BvDeBo-VU)}=
zPJnd)M2-42DoI=uCY_q0<#7LGsl^6H_;r#r-rw!{Tt^RohP{PZ<%qTJL?7c8fN$-8
zj#%Y-%IIgj9d4?BUX@VYncNdkHZlUYCjn9ywp*)R2Q3>=D`eFUWYFuhm~hErqfEqx
zUiF9xhs(=nrYGqA0BDwL*|E~mR?pNUWy~i7wyuBbt-B15``lyaiWzf2kkk5|*^A0-
zZDPC7*_bUggoDc{-!v{JW1rSzvJ<LXd&4&xzZ(&^?9P2fYq%3d;a5NP#yv$$dBXPa
z^qwyOpjdeYn#a-$7tP7Y+JRm-4IH-$RUA50(n_aT;e#n7Z~ow2w!8?5ElDQ-v%eH<
zRc=~IuNleSGVGxE0g$0Ik!$ptslcuC5ddb;8dA(y^y}NP#}acDiaaO&3oa~vYxPcd
zUvnH%n#*)QCzw1W7D@6%{)CLk*cJn~5eF5gYf3>j<cN-vLpbf3aQygMa`mpVX-ivK
zn6H|Rb+m}xc3x<E+Ap3Tv2N+B>`nH%J#dZVx8nhKt5>+(I*yVa#Eh`TN%x1bU3TmD
zLqm-L+=&g`m5mrv+lM|xfA(>%)OW(&oV+&uLovKRrht5TpX()5W8QXre=C&n;1}!2
zhFMmg@gOhiIjVPf-1$yQ9APLBr}kt=s3MPG|MSJgf0A$@O0cO?f0#@uT)(?<kjj=<
z`C><A;Y#VPtE)>IG(8+^kjzvn_(XI3GPqQJ-shlAFG3a9T^l_{;&ZlhJY|)FLYu>H
zFgL?q6hQs37gxu$^J0fCEZ9%D$<8zArt=<#{ftmz(OhbImXBI!q3cCxz2jbej%Gi&
zDoVc;-kL1bWntyg@AaX1mM(6rH9kcaRHCK6fk8{(vqV-H4EQ;0=@eIk%{`^xlQ0ot
zdOPrA!;x3uWf_d~x0<kANc7VWKp)#!hs9@7gKNrqq~l~<1GYW7bH}xT$~A0IU~>6=
z1OcwO!jFmrD%So*fw>U`ze`C=zxzOu_D^-+c1dD3EeuHB^fHwF_u5X+9Ymvy?cxob
zsD-gx!q-<ufB#LZ#Y?l8DM@FOaPw^iOk%-OW>|$j)SL|2Vq+9^h%MxEm)t`kfV&?<
zCr3kk+$~9o5tRLFap`%Qn>jT!KpB}%v1QrRW>9f55z=?4VNdc^n*)CwX-J~-k~Y1B
z=ue54OuZlPlyk}Wc`@gsO!rpBd$>a8Q^hWQx8eylN0kM_y)JQgsZJ9*lsiUJM?3pI
zJRjCL`?P}S+fjzL!E60Zbw@oP)&Dt2Mc+NO3`%^QlMVc!X@svHkSUqqXv{+C#lP>4
zsKdp53YsQt;iffIhpkl52$QGY_0w4gN!Jk#7u|*&eYP*qw(-D(aPkC=BDsT2LfU2r
z;<;Y!0&AW(pOayP!|&fdU|TqQy(~ySp9sNw85VTYEv|M32P=04T`Rw{biK|w%p39#
z5s$)7Q#v@UHm~Z}#K&>p?I<M*{rrz_$Ns=l)V-k?$<C;LDnl8_n<^m|9CX`iB&CN?
z${ENWUc=Jgyk0XjABM4Hr3ct3iUBA7WCfOTRxyxaaWDT>vx5o7B0qV!$~N|i`%Uu5
zME_NEa)ND65)Ymogq*DX*^Kj>KZ?;P*>5%9-Xo92=C?tEIy)N8F?#M}+`z3Fs<Rt;
zn=BfOYdh32_AiI#InQvJ;KC;r0aUXel$P;K6~1XZhlAaf@TkMpnD+TT90I!FqjdE5
z>L#%%EoCXSuSPeR=1Y{DIM*|<jh})0!NzaWeoqa*r+u*(ocdUX6P@SM(lW_VkAXyO
z%fq=+L?iPlShY_QHR4|6nf|O9RN6u=%h3!BCMmM{^+iGbnoXDqyd!SGTIQdsp4U!~
zzmd*L*^fclf9-uYkX8xN{^Dbg!6u>BfXaQB+o?`NY0($#EEH(VeIL9XCc~=fLrkM(
z1IdzL@^>F>OZUHVetqmyEcPiNjDYPYMX_I%KsuwD1TDQ|JBk2<x7JBs^F^M5UJ@^d
zRFhWBaR1}$rX}d<t?BvD5qO-m#d<Q9zKXa>TPnb8Oq<^rwma{Ve!7sg?Nw((rQJcD
zsN_qm#)8V3zCCa@uUi87m=B@dC5+x}J^6+QP=+7}i77}n=Yf$(pD#((pWgpWV^f*&
zXNZ=*+OGB?hGJ!Zt++|0shaLYV^T$mBNoMt#AWxTkhgL}Wi%ovZs`mR7ka{CltXHZ
zJvDD$(Rv4VJ*JYg)x}BJkZBNNYl(83dq1-Z4(2{SZPC4Wumq;#7%F2Nud-KG7<K>2
zvXuG*O&w|PCyegknNk}Q79Q!6)N29Ga@ZagXt=|)ob<-NIT$0~N(qb%xSy8N`J(yS
z&vdbQvUYar=k&^97aZET4`?FmH{YDCGn`Y^vYA?*$dvkPFlhvhExwaM|9+X{q0TWE
zuy1}`g-AUOAoafl0eu$lLxD}&<e^>-B+0|9HELgAA=Ou&^^T<3M)%E?0VAT85709U
zK#DKpJw9BagtP<K&&WoCXST?ZboWP$U2D%2$J0#Vs)HK*d*961ay9x*Q>qlN2OVEr
zu*zDkF>MNUsWsa#CYo-JHvI5htbM+-5e|yao#_Ak{eUWk2gg-rdh5Df-q=ln6sF<z
zv-Nt}3Gyy+joYru^F_;TAkiA>?ytwspDm*0qX5nzEb+!WGH>2E{&f{jF^@_4`fK3L
z_)1hwZTrsUHy5TSiC7sL@8#5eDAnR2hLFcW65M5%A#b!LS9E2+rm*!g(wmkB{{Tmy
zp!*ScdrpQOc^wyVK^8w-pQg*`lQ3UWTDsVxUl*Rje?TVvW(d8DhQ&@q?Ux@o-imlw
zX5|mOox$at(q%p3vhm{7A#1{u5FnJt<K4n^<GS23{0U?PM-<_%M6129K7C{cT$bRE
z?BWSY&DoUnmDF(=#bL0NfO9u;yL;5H?vLgh<)b#K;?cn^12h8-Gy2%ylc?)BHJd07
zx6R1Am8uded})Qg^7<4dbp~tp(=<yVT>Z%~XR^?|8qVb;?7Tb8mP}>Pp$q<oZXCf3
zDq*)ZZpEzzH}i!hh`P_=@tKmfcv5V{h9FUDE=#B%mvt+mZoqX{_GsPTW;ee^qu$R<
zzuB_i!a8(fC5bdrOqhrtC9SG2)Cnz3IWg#%$Pv`5D;AJj89!5j?+3b3i{eo09AC(v
zZ}{p7h&M08sf>Qv>~kfx*7YE<C)8*y!j@Bn{v4nx-ut}ex&S~bh{2VHmjO;-OBBS$
z9qjQ=HAQgpsEbMJ42w-;RGHbh5uaFR-mc7Kv&@bxq>uUnDj>W+H+iR2u<PE|D+01x
zau;hmqgWi?xsU0@XCHj!4qUIcgomAE-+TdQv8TN{0}o7ybMtOHGa+mZfxnP$(}8gw
z9#|*BH7JKKXv9n$L!Xny4dPkd@*=55kH2}c<>cOKnGFz;L4*e8`lVPuK~%q{ln2BN
z(x>wj-3&VDU_A6X(`7LTM*o)SHjq?5qaU$BR_oHhU^pflZF=FUy)}>KH3rz(SU5S+
z_Gy8fdVSc3Ccg|ONt;+ZUyN>UViPYR60*HcYjx2~b_;7e`nZmb!e7!l1@s%1;WH29
zGkPBLhX*EG%osG@?IsG%3Wo6s+){MzvM$q>SmZDAgGf3ezLaD+Wx=Yo0rXJDobfOf
z_igMJk(_;-9nHl4(2u<KJvIN4ALKsgMN=vsNVWh_^aMH(mv@rJj8my&n*Q;f`;RXK
z<5xe^<2mcrJX^(wRFx`dU3vK5HVw&UGWM8)&R*zv$`M$^yf`D;`uf`oFgNsO=0oar
z1`=jah)T^ZrmvCtkAC!1OBiLEzw%StBir}7nl32kN%IK^J0dNEPa%!}f^#&>Xw@=1
z`{KYY8)`;XWJ2NyJC7cSs(eecekd=8&bUNJOil9t47Fvz`#~L#>$eD*vR1c43Uyjl
z;|Bp{it{dSV3CFbp$|m7n2w|}-~5=(Kqe_jh2M2kEUudXJAqofa$7G#HUhQcURci>
zN{<9d*yMOI@VRklui8{smfG8=N5X?Sm+4ug1YUlkT#-jD{`~f^3N$`sL*{QaE}>r9
z_Ttd|oVN}0yd$P7muP;s5UY|CF4_hdq|H4+wa+9?tDe+#WfOzenq!B#1f|;r$8hbv
z7c`mz<{A++9BUJ^a%h+0sY2y7EVCCfYxS6{9D15Tgw0kOykeJ_*Zm(1oO*DgPxt1#
zo=ztP=+VP!EU%N@?}m0hw@BtHF|wb0*B%^EmDGiA7P`kq_IO7=j|hTFe!?CsXjV_(
zsjlzB-bez0p{)ERIBfS+gO8N~1496wl^<NETw+QsSrf!j957T|13x)vc>ld!P!eR~
z$%oEU?>2muYX1bhK0nf=bkc|n&w$2CnkDY=*0K=zBV_eF0nCj`>>_0pl*`wsUP&V#
z97u7Okq5Kqj3IQZIA%c%-2$-Bjo=5heN8UL<eV+MXU>%ixTv1Yt$Rwqu4l1qvM#dG
zvC)_^AXGMRNh}SU^KsD8FW{<<PCT0cJfjGYP^RlT@}eiZ!0V^rb$?L+2SF)WK3!=v
zXm<|5LG~LLZbD|aN2LBuPt~2ZeUvU7zxZ>iYa%^)nn8$_ZC(gxT;l~xj+Fo|#Sz^S
zH;;8WCU^eS@@8IhnKO6t@bC%!**vXHo^z5891*q|nGk0uu5RHQ%wx-~Of}`{&p9&H
z_1tnQXF@*>FGYp~9nt~Vt12;2T*W&p`e!$NXd-3rTFls@?`&p~OtUfEk0J-B-l1j6
z_T2zBjfq(G9JTPm$QZ3;#IC}Sb@#R=@UQZ;J$0-F(LrEw5V1I>rAgZN>bH9Ti_Z57
zb2n}}75=iisYngM&wr^C-Tm)U$M+7EQ1pnBxYKg38a4}k!L80)S6?b1d0+Ezrk|ZD
zESyJn{Ea&DlMM39G^R(Gh?KBTmaO3H436mYD;mC(+p^>jJE#m;*g%j+CTxWoGMU|)
zO)PM~@YwwkqK|)d6eKzX%IW{xvWY*>>R3wH(vmDoJX7)u1ar~;EoYduEsY6IVgP4C
zx&Et6>_lhBmRew!$J48sH)0yAAC=w2gG-)8){Yar(do0_)oU>hPd1K)8%L>i8Gpl-
zF;Cxi{{>mkHW@<I<}@H2-MnODOBb4GA?g;`c<!44-Nl4x6xt#(V$G~P=kk{6NTL1x
zI?=2@2Hyozs~;}!RkP!~`GL;yz@smVniU0iG{ACsDlJHVyaK+25ZY3%FbNZ_N=|Mb
zrN$1OmRNc=)6gjzrfn=^kSnc4|3YHvu#>pi|GwZHu^K5Fc3y+juka}6N11Sbg+GHo
z-w}|~fs?Uve93tDI`X7pRQE~P`+CQJeA!Zq=U3!{K|I9t>d9{b{!l>=n#j?}`yS)P
zTN;amN+49NfcV_7J>|QQD^EHBZD%&hhBKVM^8-RD_}jEpn0;%|Kyk;@o1IrFT(+=w
zY;m-Ld*PsReYUgsTQniCII=PssUj>?{KcvEx8oMgvN~|gpSgUjEa>sG3TQ+}Ut3zh
zFY-zSq+*1|7m<BnEg9P;BoOt&+(le3nuJZG7JaLubHCkJ<ZR9(wU~E-9&4PQK=@?Q
z*YZ%-7QWi@TI4sGWt#%N7|$&dt3XSPg!IeffSv7pPPc5hf_^Jj|1RPf=E?mKe!Z#q
z2neQsKBZ8h2d_6gqq%=vED5}=T_i3$0d}w(70?wxO+u4x=joI7slMUtxILtQ_jGK<
z+c?H}jMuvp&J44@BH+N<b0UYxF?DyC<1SE-Dh)@f7Cb(6n-;K~()m>s*l~|X{0(pJ
z|Mu^{2!LM45>+&Lx;UwRwy|IK?2o!FY8r)C{A2Z%{Z;Lt=vy!@TJU#zIq!K2JQfc+
z;>36p5qmPilfqi&(cb=I#+(mb%fFRW1!kg|92MZ+&t%iR9H-l*w6rvSoKpl_3DQ5y
zJ7dh0p<%-3%frVuZ7&|x*9|^$$KIFANYNhtQ3wS8!vzpWEnZ{0uSeung-AM9?1+1`
zhqdl9M$#B;MVDcAuHMPlDo5g0N0_bf#9iJ>`VZYT7=MP4{%Q^e;Px9&7>rv9wPg99
z+Z4N;7;SeLGRE0kt+%g@**rrfM=<p89!`S^a5)jq2oA~Kc5gg`4`z<&gMV&5acMDa
z^(Zq_gaUCJ_<Nw7fev5WW8-45swFDq>5C%~svEfJFwtabSNL0%Z4sO~CmmXmCeRu5
z4>#=zL5mtfi3*ZGtp_8R1d4HT4r&Iz>{#)<3MDkWv#lPIcW*Y6Z5Jw7kb~%5_j+-F
zKZFLW-+7c1H-voDqzjdn%EtNZyso{t4W1ZnN2*X)wY$N<`gu;iJptdf@17>(747Xi
zn%~?Te~!4S;Sv`)D5aoirKsgT=kj8;w#AColQNr$h22&^ZTNGYNnO@svC`%q=o>Rz
zt<#c#98PKK*+5zO&1~V=J3Cx1TgQA=1o6x5+;@MigK0@}zrS163v2{IS~UKOM7m7l
zhUiC!Wxc|3!WVd#uV@+O(x%_Wjw}TmiW9f5*5z^tx(ha=g|2^QBVL@Q5T&@bXOC)Z
z#o|5_s0qNGFyj{)Q|+g(0<E1Krh(a83*fgls8Fp0rtT=>UI(k3Xf6TL7fKMyxJs+(
zl~gtQ<o*}LfyQ5`VdyFIJ;(eyhEDd<mVrn-M93_Ly{+H8_HIJ(NzGPn>=l|QuVyD!
zt&KN&c+NkhTgP{*O5GgA5@tdou&L(pyMFcJy41fEN?hGuyeFPt2t*_bKgiWuyPAX$
z5X+@zIg=U0J-eSFD{5-1lw}O0L?MhUKbP`)?h{YSqkGzM=YBym2BC(V2Fj_`QMft7
z2$zSG!{IxP`Nn16<GirTvF+pKEQv_)t~Nwed^|H{!My+IWPr|jIhuW482AXGdC4$p
zDwr#&Vd*#DFhM&sTeLWp$G!(H4|TqflK)Ki+woXNN+T=(kmdS#cvqh0e)XvyigT8g
zC^fN?jB9L^5@JaLu@zXeiNEf)TwE2iy#6rQXwg-c3lTi|Te5y<wf(77BWvWD-Yk~G
z5<(4OZEO8H^biv_{c)PmsCvXA${&0{H_xKudAtC0;ErBx0#Xwd?yjS+n%Z-|{XDpN
znZMd%@d-KWI>|_Suz&{%Jci);wVuUY&Z&Sgd7`rhIZgk@7FLW0naF!q<y?8*T{8IW
z8+VBukofDxZrEhjJY^yrOfO%1yuK6XZWi36VDlscP?v8osr$LLLq_2Ai0Xf<#ujXN
zw$C)A`g`3DqP}{<(DOJP6J{Jb4|E+Y8WSNrNDM6XV}?gRCr8ve9A`9AI>X7C^}Bqp
zpn-HfoYU+a3|dT`EvcY4!6}MSxh5On@bpg}gcYNc!%P>#woLi#P)!=)Nhy22$-$l9
zV+wfJ`4*uAcUM>hCj$o;5>AHL({Z7kJE(o$IAH4AA7)qG?!s*7>_v`vr4-1l@?~%(
z$}uhyFK_C*FJ6uAJ1(h&-_Bu*euL4QZL*y^4|rtXO;3cuM;7?tB}ool?ymIO#cvc2
z@eSq0KSbp&eR9(-YTS4strNkhj*H#clNHkLZn=#}-|EQ|C#DYW!;l&`H#en2Ro~OI
zhi^iO;hzyyX^iKXrCSb9)3a4M1~w0T;Gf~IqIpP`L;g_sP<~a5`cqCN9mB8C+C^#~
zG{b|2hRGpvQz?FWecKFp_ho6C_TAynI-S|R!N<`~+_tLw@tRV2zP5mBS$q5N5O#hY
zVSt_g8Pat5WfBdO_^|MPO4Pl<qt<Oh>2_bR=;b%F@f510=i?uQ#n;{qmp8Wq@Ni^i
ziQ+f~-tbNdok}QHNY9i7DlalE&)C2z*`)o(P*sjM-qYE<?AKQzQ<9~B%%}rhRqr0f
z-844J;h-D(w2e7QO^evA+CN?<kI1dxmrHGhho%|@>w!l_MYfk?hE>h-kZAtx*wMo&
zF~YdUSa&L4Z!-{U(n8x@5@*bj4<$wYZY#kzzTgaPxsuAN{93Az`@w_Fy70>p72)Ce
z&DSiV1<pC@py2C}F>qk}J@4vtXet4zc7KFTh82xddn=pq!xit`bdbLWa3i8^?(ZB{
zoP_do`5jrPpb^QHK$cIejK8qbdkl}ELf`Mo{EV9vY2B7x)|ljjt&#7nu~JWwU2J^p
zM?%Mqj`>zMO7Lj)+i2OuxY`qh&_qPDQ*?s?L8j_K)}&YMNK5ODI_oMZUVVdZoCPDS
zl|5HKgg_V@;(OOtYd~HGWhUDS<iR$lp$;XJVKctA%WE{Fb?Dl`v|XzWU^Ukj)BmQA
z{eS3R{r_J5&HgX_f5$q|bvplxKK8%#{}unEis41=*=>EmXob4Nsfx}2{>Qw7l9g1F
Js1!2^`X7e*-9rEX

diff --git a/app/assets/stylesheets/sections/login.scss b/app/assets/stylesheets/sections/login.scss
index 8d9fd037bce..33bef59c089 100644
--- a/app/assets/stylesheets/sections/login.scss
+++ b/app/assets/stylesheets/sections/login.scss
@@ -1,7 +1,8 @@
 /* Login Page */
 body.login-page{
-  background: #474D57;
-  .container .content { padding-top: 4%; }
+  .container > .content {
+    padding-top: 20px;
+  }
 }
 
 .login-box{
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index 0fa36211739..c4729836faa 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -6,5 +6,10 @@
     .container
       .content
         %center
-          = image_tag image_path "login-logo.png"
+          %h1 GitLab
+          %p.light
+            GitLab is open source software to collaborate on code.
+            %br
+            #{link_to "Sign in", new_user_session_path} or browse for #{link_to "public projects", public_projects_path}.
+        %hr
         = yield
-- 
GitLab


From 82f6ecba8107d87f589347608ab51063764c8a06 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 24 Sep 2013 11:50:37 +0000
Subject: [PATCH 134/248] Fix commits table highlight

---
 app/assets/stylesheets/sections/commits.scss | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
index b0cf8b16260..be6fb29c817 100644
--- a/app/assets/stylesheets/sections/commits.scss
+++ b/app/assets/stylesheets/sections/commits.scss
@@ -67,6 +67,7 @@
     }
 
     table {
+      width: 100%;
       font-family: $monospace_font;
       border: none;
       margin: 0px;
@@ -504,4 +505,4 @@ li.commit {
       @extend .cgray;
     }
   }
-}
+}
\ No newline at end of file
-- 
GitLab


From a57abc72aae7013bd4b2a9717cac68acdb516656 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 24 Sep 2013 15:58:39 +0300
Subject: [PATCH 135/248] Allow non authenticated user access to public
 projects

---
 app/assets/stylesheets/common.scss            |  5 +++
 .../projects/application_controller.rb        | 23 +++++++++++++-
 app/controllers/projects_controller.rb        |  9 ++++--
 app/helpers/application_helper.rb             |  2 ++
 app/models/ability.rb                         | 31 ++++++++++++-------
 app/views/layouts/public.html.haml            | 23 ++++++++++----
 app/views/projects/_clone_panel.html.haml     |  2 +-
 app/views/projects/commits/_head.html.haml    |  2 +-
 app/views/projects/issues/_head.html.haml     |  7 +++--
 9 files changed, 79 insertions(+), 25 deletions(-)

diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss
index 6d80b22b3aa..1572227ec3a 100644
--- a/app/assets/stylesheets/common.scss
+++ b/app/assets/stylesheets/common.scss
@@ -382,3 +382,8 @@ table {
   width: 50px;
   min-height: 100px;
 }
+
+.navbar-gitlab .navbar-inner .nav > li .btn-sign-in {
+  @extend .btn-new;
+  padding: 5px 15px;
+}
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index 1f2a75175cf..d525bd4a700 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -1,5 +1,26 @@
 class Projects::ApplicationController < ApplicationController
   before_filter :project
   before_filter :repository
-  layout 'projects'
+  layout :determine_layout
+
+  def authenticate_user!
+    # Restrict access to Projects area only
+    # for non-signed users
+    if !current_user
+      id = params[:project_id] || params[:id]
+      @project = Project.find_with_namespace(id)
+
+      return if @project && @project.public
+    end
+
+    super
+  end
+
+  def determine_layout
+    if current_user
+      'projects'
+    else
+      'public'
+    end
+  end
 end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 23b54ec44a8..9ba2a758b8a 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -1,4 +1,5 @@
 class ProjectsController < Projects::ApplicationController
+  skip_before_filter :authenticate_user!, only: [:show]
   skip_before_filter :project, only: [:new, :create]
   skip_before_filter :repository, only: [:new, :create]
 
@@ -54,6 +55,8 @@ class ProjectsController < Projects::ApplicationController
   end
 
   def show
+    return authenticate_user! unless @project.public
+
     limit = (params[:limit] || 20).to_i
 
     @events = @project.events.recent
@@ -69,8 +72,10 @@ class ProjectsController < Projects::ApplicationController
         if @project.empty_repo?
           render "projects/empty"
         else
-          @last_push = current_user.recent_push(@project.id)
-          render :show
+          if current_user
+            @last_push = current_user.recent_push(@project.id)
+          end
+          render :show, layout: current_user ? "project" : "public"
         end
       end
       format.js
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 4209b081bfa..7e5c10fee05 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -90,6 +90,8 @@ module ApplicationHelper
   end
 
   def search_autocomplete_source
+    return unless current_user
+
     projects = current_user.authorized_projects.map { |p| { label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) } }
     groups = current_user.authorized_groups.map { |group| { label: "group: #{simple_sanitize(group.name)}", url: group_path(group) } }
 
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 8335829f919..7f044b220a5 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -1,6 +1,7 @@
 class Ability
   class << self
     def allowed(user, subject)
+      return not_auth_abilities(user, subject) if user.nil?
       return [] unless user.kind_of?(User)
       return [] if user.blocked?
 
@@ -17,6 +18,24 @@ class Ability
       end.concat(global_abilities(user))
     end
 
+    # List of possible abilities
+    # for non-authenticated user
+    def not_auth_abilities(user, subject)
+      project = if subject.kind_of?(Project)
+                  subject
+                elsif subject.respond_to?(:project)
+                  subject.project
+                else
+                  nil
+                end
+
+      if project && project.public
+        public_project_rules
+      else
+        []
+      end
+    end
+
     def global_abilities(user)
       rules = []
       rules << :create_group if user.can_create_group
@@ -58,19 +77,9 @@ class Ability
     end
 
     def public_project_rules
-      [
+      project_guest_rules + [
         :download_code,
         :fork_project,
-        :read_project,
-        :read_wiki,
-        :read_issue,
-        :read_milestone,
-        :read_project_snippet,
-        :read_team_member,
-        :read_merge_request,
-        :read_note,
-        :write_issue,
-        :write_note
       ]
     end
 
diff --git a/app/views/layouts/public.html.haml b/app/views/layouts/public.html.haml
index 7dce0cbeae2..c1fe5fcae7e 100644
--- a/app/views/layouts/public.html.haml
+++ b/app/views/layouts/public.html.haml
@@ -1,7 +1,7 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: "Public Projects"
-  %body{class: "#{app_theme} application", :'data-page' => body_data_page}
+  %body{class: "ui_mars application", :'data-page' => body_data_page}
     - if current_user
       = render "layouts/head_panel", title: "Public Projects"
     - else
@@ -13,7 +13,12 @@
               = link_to public_root_path, class: "home" do
                 %h1 GITLAB
               %span.separator
-            %h1.project_name Public Projects
+            %h1.project_name
+              - if @project
+                = project_title(@project)
+              - else
+                Public Projects
+
             %ul.nav
               %li
                 %a
@@ -21,8 +26,14 @@
                     %i.icon-refresh.icon-spin
                     Loading...
               %li
-                = link_to "Sign in", new_session_path(:user)
+                = link_to "Sign in", new_session_path(:user), class: 'btn btn-sign-in'
+
+    - if @project
+      %nav.main-nav
+        .container= render 'layouts/nav/project'
 
-    .container.navless-container
-      .content
-        = yield
+      .container
+        .content= yield
+    - else
+      .container.navless-container
+        .content= yield
diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml
index 7228c760d27..c5ab64505c6 100644
--- a/app/views/projects/_clone_panel.html.haml
+++ b/app/views/projects/_clone_panel.html.haml
@@ -5,7 +5,7 @@
     .span3.pull-right
       .pull-right
         - unless @project.empty_repo?
-          - if can?(current_user, :fork_project, @project) && @project.namespace != current_user.namespace
+          - if current_user && can?(current_user, :fork_project, @project) && @project.namespace != current_user.namespace
             - if current_user.already_forked?(@project)
               = link_to project_path(current_user.fork_of(@project)), class: 'btn grouped disabled' do
                 %i.icon-code-fork
diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml
index 624604142b1..c2da9f273b3 100644
--- a/app/views/projects/commits/_head.html.haml
+++ b/app/views/projects/commits/_head.html.haml
@@ -21,7 +21,7 @@
       Stats
 
 
-  - if current_controller?(:commits) && current_user.private_token
+  - if current_user && current_controller?(:commits) && current_user.private_token
     %li.pull-right
       = link_to project_commits_path(@project, @ref, {format: :atom, private_token: current_user.private_token}), title: "Feed" do
         %i.icon-rss
diff --git a/app/views/projects/issues/_head.html.haml b/app/views/projects/issues/_head.html.haml
index 44d14d5cdf9..438cc02b477 100644
--- a/app/views/projects/issues/_head.html.haml
+++ b/app/views/projects/issues/_head.html.haml
@@ -5,6 +5,7 @@
     = link_to 'Milestones', project_milestones_path(@project), class: "tab"
   = nav_link(controller: :labels) do
     = link_to 'Labels', project_labels_path(@project), class: "tab"
-  %li.pull-right
-    = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
-      %i.icon-rss
+  - if current_user
+    %li.pull-right
+      = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
+        %i.icon-rss
-- 
GitLab


From 22c26c7a6cf6872fe918f42e30735fc6caba5a4b Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 24 Sep 2013 16:00:21 +0300
Subject: [PATCH 136/248] Point to project page from public area

---
 app/controllers/public/projects_controller.rb | 13 -----
 app/views/public/projects/_tree.html.haml     |  5 --
 app/views/public/projects/index.html.haml     |  2 +-
 app/views/public/projects/show.html.haml      | 49 -------------------
 4 files changed, 1 insertion(+), 68 deletions(-)
 delete mode 100644 app/views/public/projects/_tree.html.haml
 delete mode 100644 app/views/public/projects/show.html.haml

diff --git a/app/controllers/public/projects_controller.rb b/app/controllers/public/projects_controller.rb
index 3504bd3f1a5..87e903a1d2d 100644
--- a/app/controllers/public/projects_controller.rb
+++ b/app/controllers/public/projects_controller.rb
@@ -10,17 +10,4 @@ class Public::ProjectsController < ApplicationController
     @projects = @projects.search(params[:search]) if params[:search].present?
     @projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(20)
   end
-
-  def show
-    @project = Project.public_only.find_with_namespace(params[:id])
-    render_404 and return unless @project
-
-    @repository = @project.repository
-    unless @project.empty_repo?
-      @recent_tags = @repository.tags.first(10)
-
-      @commit = @repository.commit(params[:ref])
-      @tree = Tree.new(@repository, @commit.id)
-    end
-  end
 end
diff --git a/app/views/public/projects/_tree.html.haml b/app/views/public/projects/_tree.html.haml
deleted file mode 100644
index bd09c236a0b..00000000000
--- a/app/views/public/projects/_tree.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-- if tree.readme
-  = render "projects/tree/readme", readme: tree.readme
-- else
-  .alert
-    %h3.nothing_here_message This project does not have README file
diff --git a/app/views/public/projects/index.html.haml b/app/views/public/projects/index.html.haml
index 7dbe560e7fc..bea99b54ef7 100644
--- a/app/views/public/projects/index.html.haml
+++ b/app/views/public/projects/index.html.haml
@@ -17,7 +17,7 @@
       %li
         .project-title
           %i.icon-share.cgray
-          = link_to public_project_path(project) do
+          = link_to project_path(project) do
             %strong= project.name_with_namespace
           .pull-right
             %pre.public-clone git clone #{project.http_url_to_repo}
diff --git a/app/views/public/projects/show.html.haml b/app/views/public/projects/show.html.haml
deleted file mode 100644
index 195b9bc07d2..00000000000
--- a/app/views/public/projects/show.html.haml
+++ /dev/null
@@ -1,49 +0,0 @@
-%h3.page-title
-  = @project.name_with_namespace
-  .pull-right
-    %pre.public-clone git clone #{@project.http_url_to_repo}
-  .pull-right
-    - if current_user
-      = link_to 'Browse project', @project, class: 'btn btn-create append-right-10'
-
-
-%div
-  = link_to public_root_path do
-    &larr; To projects list
-  .pull-right
-    %span.light= @project.description
-
-%br
-.row
-  - unless @project.empty_repo?
-    .span9
-      = render 'tree', tree: @tree
-    .span3
-      %h5 Repository:
-      %div
-        %p
-          %span.light Bare size is
-          #{@project.repository.size} MB
-
-        %p
-          = pluralize(@repository.round_commit_count, 'commit')
-        %p
-          = pluralize(@repository.branch_names.count, 'branch')
-        %p
-          = pluralize(@repository.tag_names.count, 'tag')
-
-      - if @recent_tags.present?
-        %hr
-        %h5 Most Recent Tags:
-        %ul.unstyled
-          - @recent_tags.each do |tag|
-            %li
-              %p
-                %i.icon-tag
-                %strong= tag.name
-                %small.light.pull-right
-                  %i.icon-calendar
-                    = time_ago_in_words(tag.commit.committed_date)
-                  ago
-  - else
-    = 'Empty Repository'
-- 
GitLab


From c50fda56b66861910a2ac361b4959cb4102f97a0 Mon Sep 17 00:00:00 2001
From: Izaak Alpert <ialpert@blackberry.com>
Date: Tue, 24 Sep 2013 09:22:46 -0400
Subject: [PATCH 137/248] Used pagnation function from api helpers

Change-Id: I1bdd3608d3b46924b5da3ae282c99f85ee4e0dab
---
 doc/api/projects.md |  4 ++--
 lib/api/projects.rb | 10 ++++------
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/doc/api/projects.md b/doc/api/projects.md
index 380f6f21ce8..5150331e7d7 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -497,5 +497,5 @@ GET /projects/search/:query
 Parameters:
 
 +   query (required) - A string contained in the project name
-+   per_page (optional) - number of projects to return per page, defaults to 20
-+   offset (optional) - the offset in pages to retrieve
++   per_page (optional) - number of projects to return per page
++   page (optional) - the page to retrieve
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index d17b791dccc..cf357b23c40 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -266,16 +266,14 @@ module API
       #
       # Parameters:
       #   query (required) - A string contained in the project name
-      #   per_page (optional) - number of projects to return per page, defaults to 20
-      #   offset (optional) - the offset in pages to retrieve
+      #   per_page (optional) - number of projects to return per page
+      #   page (optional) - the page to retrieve
       # Example Request:
       #   GET /projects/search/:query
       get "/search/:query" do
-        limit = (params[:per_page] || 20).to_i
-        offset = (params[:page] || 0).to_i * limit
         ids = current_user.authorized_projects.map(&:id)
-        projects = Project.where("(id in (?) OR public = true) AND (name LIKE (?))", ids, "%#{params[:query]}%").limit(limit).offset(offset)
-        present projects, with: Entities::Project
+        projects = Project.where("(id in (?) OR public = true) AND (name LIKE (?))", ids, "%#{params[:query]}%")
+        present paginate(projects), with: Entities::Project
       end
     end
   end
-- 
GitLab


From 7519e6f6a87b9e1f3ecf7c6bbcbcf03237e3a5b9 Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Tue, 24 Sep 2013 20:13:25 +0200
Subject: [PATCH 138/248] Add rack attack gem.

---
 Gemfile      | 3 +++
 Gemfile.lock | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/Gemfile b/Gemfile
index ccefe0af7a5..6530139cf5f 100644
--- a/Gemfile
+++ b/Gemfile
@@ -120,6 +120,9 @@ gem "underscore-rails", "~> 1.4.4"
 # Sanitize user input
 gem "sanitize"
 
+# Protect against bruteforcing
+gem "rack-attack"
+
 group :assets do
   gem "sass-rails"
   gem "coffee-rails"
diff --git a/Gemfile.lock b/Gemfile.lock
index 9de7a0f876b..d6739cb87ac 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -334,6 +334,8 @@ GEM
     rack (1.4.5)
     rack-accept (0.4.5)
       rack (>= 0.4)
+    rack-attack (2.2.1)
+      rack
     rack-cache (1.2)
       rack (>= 0.4)
     rack-mini-profiler (0.1.26)
@@ -603,6 +605,7 @@ DEPENDENCIES
   poltergeist (~> 1.4.1)
   pry
   quiet_assets (~> 1.0.1)
+  rack-attack
   rack-mini-profiler
   rails (= 3.2.13)
   rails-dev-tweaks
-- 
GitLab


From ed27da8df09872cc21e970964dd52424dc214f48 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 24 Sep 2013 22:12:48 +0300
Subject: [PATCH 139/248] Fix password update

---
 app/controllers/profiles_controller.rb | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index 780f47d9960..75f12f8a6af 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -33,8 +33,8 @@ class ProfilesController < ApplicationController
   end
 
   def update_password
-    params[:user].select! do |key, value|
-      %w(current_password password password_confirmation).include?(key.to_s)
+    password_attributes = params[:user].select do |key, value|
+      %w(password password_confirmation).include?(key.to_s)
     end
 
     unless @user.valid_password?(params[:user][:current_password])
@@ -42,7 +42,7 @@ class ProfilesController < ApplicationController
       return
     end
 
-    if @user.update_attributes(params[:user])
+    if @user.update_attributes(password_attributes)
       flash[:notice] = "Password was successfully updated. Please login with it"
       redirect_to new_user_session_path
     else
-- 
GitLab


From 88d795489e7adf20ee0b1511f375a9282f338072 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 24 Sep 2013 22:13:28 +0300
Subject: [PATCH 140/248] Remove writing issues/notes from non-auth user
 abilities

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

diff --git a/app/models/ability.rb b/app/models/ability.rb
index 7f044b220a5..26988c5e6a7 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -30,7 +30,17 @@ class Ability
                 end
 
       if project && project.public
-        public_project_rules
+        [
+          :read_project,
+          :read_wiki,
+          :read_issue,
+          :read_milestone,
+          :read_project_snippet,
+          :read_team_member,
+          :read_merge_request,
+          :read_note,
+          :download_code
+        ]
       else
         []
       end
-- 
GitLab


From 27e5b20be4a304a620bafcda5940977a708af053 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 24 Sep 2013 22:14:03 +0300
Subject: [PATCH 141/248] Different layout for browsing public area and public
 project page while not logged-in

---
 .../layouts/_public_head_panel.html.haml      | 22 ++++++++++++
 app/views/layouts/public.html.haml            | 34 ++-----------------
 app/views/layouts/public_projects.html.haml   |  9 +++++
 3 files changed, 34 insertions(+), 31 deletions(-)
 create mode 100644 app/views/layouts/_public_head_panel.html.haml
 create mode 100644 app/views/layouts/public_projects.html.haml

diff --git a/app/views/layouts/_public_head_panel.html.haml b/app/views/layouts/_public_head_panel.html.haml
new file mode 100644
index 00000000000..3c4bd857c22
--- /dev/null
+++ b/app/views/layouts/_public_head_panel.html.haml
@@ -0,0 +1,22 @@
+%header.navbar.navbar-static-top.navbar-gitlab
+  .navbar-inner
+    .container
+      %div.app_logo
+        %span.separator
+        = link_to public_root_path, class: "home" do
+          %h1 GITLAB
+        %span.separator
+      %h1.project_name
+        - if @project
+          = project_title(@project)
+        - else
+          Public Projects
+
+      %ul.nav
+        %li
+          %a
+            %div.hide.turbolink-spinner
+              %i.icon-refresh.icon-spin
+              Loading...
+        %li
+          = link_to "Sign in", new_session_path(:user), class: 'btn btn-sign-in'
diff --git a/app/views/layouts/public.html.haml b/app/views/layouts/public.html.haml
index c1fe5fcae7e..f922dcc4203 100644
--- a/app/views/layouts/public.html.haml
+++ b/app/views/layouts/public.html.haml
@@ -5,35 +5,7 @@
     - if current_user
       = render "layouts/head_panel", title: "Public Projects"
     - else
-      %header.navbar.navbar-static-top.navbar-gitlab
-        .navbar-inner
-          .container
-            %div.app_logo
-              %span.separator
-              = link_to public_root_path, class: "home" do
-                %h1 GITLAB
-              %span.separator
-            %h1.project_name
-              - if @project
-                = project_title(@project)
-              - else
-                Public Projects
+      = render "layouts/public_head_panel"
 
-            %ul.nav
-              %li
-                %a
-                  %div.hide.turbolink-spinner
-                    %i.icon-refresh.icon-spin
-                    Loading...
-              %li
-                = link_to "Sign in", new_session_path(:user), class: 'btn btn-sign-in'
-
-    - if @project
-      %nav.main-nav
-        .container= render 'layouts/nav/project'
-
-      .container
-        .content= yield
-    - else
-      .container.navless-container
-        .content= yield
+    .container.navless-container
+      .content= yield
diff --git a/app/views/layouts/public_projects.html.haml b/app/views/layouts/public_projects.html.haml
new file mode 100644
index 00000000000..cfe6a63055a
--- /dev/null
+++ b/app/views/layouts/public_projects.html.haml
@@ -0,0 +1,9 @@
+!!! 5
+%html{ lang: "en"}
+  = render "layouts/head", title: @project.name_with_namespace
+  %body{class: "ui_mars application", :'data-page' => body_data_page}
+    = render "layouts/public_head_panel"
+    %nav.main-nav
+      .container= render 'layouts/nav/project'
+    .container
+      .content= yield
-- 
GitLab


From 4205a2c7443dd3ca63ef075f0338f69ba7853740 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 24 Sep 2013 22:14:28 +0300
Subject: [PATCH 142/248] Public projects feature - step2

* Render right layout depends on current_user
* show sample git username/email when repo is empty
* Show extra info when browsing public area
* Fixed some tests related to public projects
* show comments in read-only for public projects
* Remove old public routing
---
 app/assets/stylesheets/sections/projects.scss | 24 +++++---------
 .../projects/application_controller.rb        |  2 +-
 app/controllers/projects_controller.rb        | 11 ++++---
 app/helpers/projects_helper.rb                | 16 ++++++++++
 app/views/projects/empty.html.haml            |  4 +--
 app/views/projects/notes/_note.html.haml      |  2 +-
 app/views/public/projects/index.html.haml     | 31 +++++++++++++------
 config/routes.rb                              |  2 --
 features/public/public_projects.feature       |  9 +++---
 features/steps/public/projects_feature.rb     | 15 +++++++--
 10 files changed, 72 insertions(+), 44 deletions(-)

diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss
index f2707f62378..0491b68db57 100644
--- a/app/assets/stylesheets/sections/projects.scss
+++ b/app/assets/stylesheets/sections/projects.scss
@@ -79,21 +79,6 @@ ul.nav.nav-projects-tabs {
   margin: 0px;
 }
 
-.public-projects {
-  li {
-    .project-title {
-      font-size: 14px;
-      line-height: 2;
-      font-weight: normal;
-    }
-
-    .description {
-      margin-left: 15px;
-      color: #aaa;
-    }
-  }
-}
-
 .my-projects {
   li {
     .project-title {
@@ -110,7 +95,6 @@ ul.nav.nav-projects-tabs {
   }
 }
 
-
 .public-clone {
   background: #333;
   color: #f5f5f5;
@@ -123,3 +107,11 @@ ul.nav.nav-projects-tabs {
   position: relative;
   top: -5px;
 }
+
+.public-projects .repo-info {
+  color: #777;
+
+  a {
+    color: #777;
+  }
+}
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index d525bd4a700..8fd4565f367 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -20,7 +20,7 @@ class Projects::ApplicationController < ApplicationController
     if current_user
       'projects'
     else
-      'public'
+      'public_projects'
     end
   end
 end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 9ba2a758b8a..f31fb666e3e 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -55,10 +55,9 @@ class ProjectsController < Projects::ApplicationController
   end
 
   def show
-    return authenticate_user! unless @project.public
+    return authenticate_user! unless @project.public || current_user
 
     limit = (params[:limit] || 20).to_i
-
     @events = @project.events.recent
     @events = event_filter.apply_filter(@events)
     @events = @events.limit(limit).offset(params[:offset] || 0)
@@ -70,12 +69,12 @@ class ProjectsController < Projects::ApplicationController
     respond_to do |format|
       format.html do
         if @project.empty_repo?
-          render "projects/empty"
+          render "projects/empty", layout: user_layout
         else
           if current_user
             @last_push = current_user.recent_push(@project.id)
           end
-          render :show, layout: current_user ? "project" : "public"
+          render :show, layout: user_layout
         end
       end
       format.js
@@ -126,4 +125,8 @@ class ProjectsController < Projects::ApplicationController
   def set_title
     @title = 'New Project'
   end
+
+  def user_layout
+    current_user ? "projects" : "public_projects"
+  end
 end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 3a1cf59fd1a..9071c688df1 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -103,4 +103,20 @@ module ProjectsHelper
 
     nav_tabs.flatten
   end
+
+  def git_user_name
+    if current_user
+      current_user.name
+    else
+      "Your name"
+    end
+  end
+
+  def git_user_email
+    if current_user
+      current_user.email
+    else
+      "your@email.com"
+    end
+  end
 end
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 001857cefda..9f3502e90de 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -16,8 +16,8 @@
       %legend Git global setup:
       %pre.dark
         :preserve
-          git config --global user.name "#{current_user.name}"
-          git config --global user.email "#{current_user.email}"
+          git config --global user.name "#{git_user_name}"
+          git config --global user.email "#{git_user_email}"
 
     %fieldset
       %legend Create Repository
diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml
index fbc924c4e1d..324b698f3b5 100644
--- a/app/views/projects/notes/_note.html.haml
+++ b/app/views/projects/notes/_note.html.haml
@@ -5,7 +5,7 @@
         %i.icon-link
         Link here
       &nbsp;
-      - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project)
+      - if(note.author_id == current_user.try(:id)) || can?(current_user, :admin_note, @project)
         = link_to "#", title: "Edit comment", class: "js-note-edit" do
           %i.icon-edit
           Edit
diff --git a/app/views/public/projects/index.html.haml b/app/views/public/projects/index.html.haml
index bea99b54ef7..21aee644579 100644
--- a/app/views/public/projects/index.html.haml
+++ b/app/views/public/projects/index.html.haml
@@ -2,29 +2,40 @@
   .span6
     %h3.page-title
       Projects (#{@projects.total_count})
-      %small with read-only access
+    .light
+      You can browse public projects in read-only mode until signed in.
+
   .span6
     .pull-right
       = form_tag public_projects_path, method: :get, class: 'form-inline' do |f|
         .search-holder
-          .controls
-            = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "span3 search-text-input", id: "projects_search"
-            = submit_tag 'Search', class: "btn btn-primary wide"
-
+          = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "span3 search-text-input", id: "projects_search"
+          = submit_tag 'Search', class: "btn btn-primary wide"
+%hr
 .public-projects
-  %ul.bordered-list
+  %ul.bordered-list.top-list
     - @projects.each do |project|
       %li
-        .project-title
-          %i.icon-share.cgray
+        %h4
           = link_to project_path(project) do
-            %strong= project.name_with_namespace
+            = project.name_with_namespace
           .pull-right
             %pre.public-clone git clone #{project.http_url_to_repo}
 
         - if project.description.present?
-          %div.description
+          %p
             = project.description
+
+        .repo-info
+          - unless project.empty_repo?
+            = link_to pluralize(project.repository.round_commit_count, 'commit'), project_commits_path(project, project.default_branch)
+            &middot;
+            = link_to pluralize(project.repository.branch_names.count, 'branch'), project_branches_path(project)
+            &middot;
+            = link_to pluralize(project.repository.tag_names.count, 'tag'), project_tags_path(project)
+          - else
+            %i.icon-warning-sign
+            Empty repository
     - unless @projects.present?
       %h3.nothing_here_message No public projects
 
diff --git a/config/routes.rb b/config/routes.rb
index 2b444c2a296..9d47faa19d5 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -55,8 +55,6 @@ Gitlab::Application.routes.draw do
   #
   namespace :public do
     resources :projects, only: [:index]
-    resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, only: [:show]
-
     root to: "projects#index"
   end
 
diff --git a/features/public/public_projects.feature b/features/public/public_projects.feature
index 1866d3f47fe..178a769194c 100644
--- a/features/public/public_projects.feature
+++ b/features/public/public_projects.feature
@@ -9,11 +9,10 @@ Feature: Public Projects Feature
     And I should not see project "Enterprise"
 
   Scenario: I visit public project page
-    When I visit public page for "Community" project
-    Then I should see public project details
-    And I should see project readme
+    When I visit project "Community" page
+    Then I should see project "Community" home page
 
   Scenario: I visit an empty public project page
     Given public empty project "Empty Public Project"
-    When I visit empty public project page
-    Then I should see empty public project details
\ No newline at end of file
+    When I visit empty project page
+    Then I should see empty public project details
diff --git a/features/steps/public/projects_feature.rb b/features/steps/public/projects_feature.rb
index 2268e9b9c5e..2f2c4de0b2a 100644
--- a/features/steps/public/projects_feature.rb
+++ b/features/steps/public/projects_feature.rb
@@ -31,19 +31,28 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps
     create :project, name: 'Empty Public Project', public: true
   end
 
-  step 'I visit empty public project page' do
+  step 'I visit empty project page' do
     project = Project.find_by_name('Empty Public Project')
-    visit public_project_path(project)
+    visit project_path(project)
+  end
+
+  step 'I visit project "Community" page' do
+    project = Project.find_by_name('Community')
+    visit project_path(project)
   end
 
   step 'I should see empty public project details' do
-    page.should have_content 'Empty Repository'
+    page.should have_content 'Git global setup'
   end
 
   step 'private project "Enterprise"' do
     create :project, name: 'Enterprise'
   end
 
+  step 'I should see project "Community" home page' do
+    page.should have_content 'Repo size is'
+  end
+
   private
 
   def project
-- 
GitLab


From 22b18274190908587a366f73f55d681c910fe665 Mon Sep 17 00:00:00 2001
From: Johannes Becker <jb@jbecker.it>
Date: Wed, 25 Sep 2013 00:56:25 +0200
Subject: [PATCH 143/248] Simple PivotalTracker Source Commits Service

---
 app/models/pivotaltracker_service.rb | 57 ++++++++++++++++++++++++++++
 app/models/project.rb                |  3 +-
 2 files changed, 59 insertions(+), 1 deletion(-)
 create mode 100644 app/models/pivotaltracker_service.rb

diff --git a/app/models/pivotaltracker_service.rb b/app/models/pivotaltracker_service.rb
new file mode 100644
index 00000000000..eb7ea5f2113
--- /dev/null
+++ b/app/models/pivotaltracker_service.rb
@@ -0,0 +1,57 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id          :integer          not null, primary key
+#  type        :string(255)
+#  title       :string(255)
+#  token       :string(255)
+#  project_id  :integer          not null
+#  created_at  :datetime         not null
+#  updated_at  :datetime         not null
+#  active      :boolean          default(FALSE), not null
+#
+
+class PivotaltrackerService < Service
+  include HTTParty
+
+  attr_accessible :subdomain, :room
+
+  validates :token, presence: true, if: :activated?
+
+  def title
+    'PivotalTracker'
+  end
+
+  def description
+    'Project Management Software (Source Commits Endpoint)'
+  end
+
+  def to_param
+    'pivotaltracker'
+  end
+
+  def fields
+    [
+      { type: 'text', name: 'token', placeholder: '' }
+    ]
+  end
+
+  def execute(push)
+    url = 'https://www.pivotaltracker.com/services/v5/source_commits'
+    push[:commits].each do |commit|
+      message = {'source_commit' =>
+                  {'commit_id' => commit[:id],
+                   'author' => commit[:author][:name],
+                   'url' => commit[:url],
+                   'message' => commit[:message]}
+                }
+      status = PivotaltrackerService.post(url,
+                     body: message.to_json,
+                     headers: {'Content-Type' => 'application/json',
+                               'X-TrackerToken' => token}
+                    )
+    end
+  end
+
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index f4d915179e8..63cd3505ec4 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -46,6 +46,7 @@ class Project < ActiveRecord::Base
   has_one :last_event, class_name: 'Event', order: 'events.created_at DESC', foreign_key: 'project_id'
   has_one :gitlab_ci_service, dependent: :destroy
   has_one :campfire_service, dependent: :destroy
+  has_one :pivotaltracker_service, dependent: :destroy
   has_one :hipchat_service, dependent: :destroy
   has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
   has_one :forked_from_project, through: :forked_project_link
@@ -220,7 +221,7 @@ class Project < ActiveRecord::Base
   end
 
   def available_services_names
-    %w(gitlab_ci campfire hipchat)
+    %w(gitlab_ci campfire hipchat pivotaltracker)
   end
 
   def gitlab_ci?
-- 
GitLab


From c198300ecd8150c5230652f558bfab6ec26b1a4b Mon Sep 17 00:00:00 2001
From: Johannes Becker <jb@jbecker.it>
Date: Wed, 25 Sep 2013 01:09:33 +0200
Subject: [PATCH 144/248] Remove not needed attr_accessible

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

diff --git a/app/models/pivotaltracker_service.rb b/app/models/pivotaltracker_service.rb
index eb7ea5f2113..4efdafa9791 100644
--- a/app/models/pivotaltracker_service.rb
+++ b/app/models/pivotaltracker_service.rb
@@ -15,8 +15,6 @@
 class PivotaltrackerService < Service
   include HTTParty
 
-  attr_accessible :subdomain, :room
-
   validates :token, presence: true, if: :activated?
 
   def title
-- 
GitLab


From bf9853115d1746b54762fbcf5574500b828f86a4 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 25 Sep 2013 13:27:16 +0300
Subject: [PATCH 145/248] Group security tests

---
 spec/features/security/group_access_spec.rb | 83 +++++++++++++++++++++
 1 file changed, 83 insertions(+)
 create mode 100644 spec/features/security/group_access_spec.rb

diff --git a/spec/features/security/group_access_spec.rb b/spec/features/security/group_access_spec.rb
new file mode 100644
index 00000000000..b6167174f20
--- /dev/null
+++ b/spec/features/security/group_access_spec.rb
@@ -0,0 +1,83 @@
+require 'spec_helper'
+
+describe "Group access" do
+  describe "GET /projects/new" do
+    it { new_group_path.should be_allowed_for :admin }
+    it { new_group_path.should be_allowed_for :user }
+    it { new_group_path.should be_denied_for :visitor }
+  end
+
+  describe "Group" do
+    let(:group) { create(:group) }
+
+    let(:master)   { create(:user) }
+    let(:reporter) { create(:user) }
+    let(:guest)    { create(:user) }
+
+    before do
+      group.add_user(master, Gitlab::Access::MASTER)
+      group.add_user(reporter, Gitlab::Access::REPORTER)
+      group.add_user(guest, Gitlab::Access::GUEST)
+    end
+
+    describe "GET /groups/:path" do
+      subject { group_path(group) }
+
+      it { should be_allowed_for group.owner }
+      it { should be_allowed_for master }
+      it { should be_allowed_for reporter }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for guest }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
+    end
+
+    describe "GET /groups/:path/issues" do
+      subject { issues_group_path(group) }
+
+      it { should be_allowed_for group.owner }
+      it { should be_allowed_for master }
+      it { should be_allowed_for reporter }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for guest }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
+    end
+
+    describe "GET /groups/:path/merge_requests" do
+      subject { merge_requests_group_path(group) }
+
+      it { should be_allowed_for group.owner }
+      it { should be_allowed_for master }
+      it { should be_allowed_for reporter }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for guest }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
+    end
+
+    describe "GET /groups/:path/members" do
+      subject { members_group_path(group) }
+
+      it { should be_allowed_for group.owner }
+      it { should be_allowed_for master }
+      it { should be_allowed_for reporter }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for guest }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
+    end
+
+    describe "GET /groups/:path/edit" do
+      subject { edit_group_path(group) }
+
+      it { should be_allowed_for group.owner }
+      it { should be_denied_for master }
+      it { should be_denied_for reporter }
+      it { should be_allowed_for :admin }
+      it { should be_denied_for guest }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
+    end
+  end
+end
-- 
GitLab


From aa8ba5ec6383ad1605fe866b4fc4fb1040c246e9 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 25 Sep 2013 14:04:01 +0300
Subject: [PATCH 146/248] Public/Private projects security specs

---
 .../security/project/private_access_spec.rb   | 218 ++++++++
 .../security/project/public_access_spec.rb    | 251 ++++++++++
 spec/features/security/project_access_spec.rb | 474 ------------------
 3 files changed, 469 insertions(+), 474 deletions(-)
 create mode 100644 spec/features/security/project/private_access_spec.rb
 create mode 100644 spec/features/security/project/public_access_spec.rb
 delete mode 100644 spec/features/security/project_access_spec.rb

diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb
new file mode 100644
index 00000000000..7f3f8c50f02
--- /dev/null
+++ b/spec/features/security/project/private_access_spec.rb
@@ -0,0 +1,218 @@
+require 'spec_helper'
+
+describe "Private Project Access" do
+  let(:project) { create(:project_with_code) }
+
+  let(:master)   { create(:user) }
+  let(:guest)    { create(:user) }
+  let(:reporter) { create(:user) }
+
+  before do
+    # full access
+    project.team << [master, :master]
+
+    # readonly
+    project.team << [reporter, :reporter]
+  end
+
+  describe "GET /:project_path" do
+    subject { project_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/tree/master" do
+    subject { project_tree_path(project, project.repository.root_ref) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/commits/master" do
+    subject { project_commits_path(project, project.repository.root_ref, limit: 1) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/commit/:sha" do
+    subject { project_commit_path(project, project.repository.commit) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/compare" do
+    subject { project_compare_index_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/team" do
+    subject { project_team_index_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/wall" do
+    subject { project_wall_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/blob" do
+    before do
+      commit = project.repository.commit
+      path = commit.tree.contents.select { |i| i.is_a?(Grit::Blob) }.first.name
+      @blob_path = project_blob_path(project, File.join(commit.id, path))
+    end
+
+    it { @blob_path.should be_allowed_for master }
+    it { @blob_path.should be_allowed_for reporter }
+    it { @blob_path.should be_allowed_for :admin }
+    it { @blob_path.should be_denied_for guest }
+    it { @blob_path.should be_denied_for :user }
+    it { @blob_path.should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/edit" do
+    subject { edit_project_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/deploy_keys" do
+    subject { project_deploy_keys_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/issues" do
+    subject { project_issues_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/snippets" do
+    subject { project_snippets_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/merge_requests" do
+    subject { project_merge_requests_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/branches/recent" do
+    subject { recent_project_branches_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/branches" do
+    subject { project_branches_path(project) }
+
+    before do
+      # Speed increase
+      Project.any_instance.stub(:branches).and_return([])
+    end
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/tags" do
+    subject { project_tags_path(project) }
+
+    before do
+      # Speed increase
+      Project.any_instance.stub(:tags).and_return([])
+    end
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/hooks" do
+    subject { project_hooks_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+end
diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb
new file mode 100644
index 00000000000..267643fd8ef
--- /dev/null
+++ b/spec/features/security/project/public_access_spec.rb
@@ -0,0 +1,251 @@
+require 'spec_helper'
+
+describe "Public Project Access" do
+  let(:project) { create(:project_with_code) }
+
+  let(:master) { create(:user) }
+  let(:guest) { create(:user) }
+  let(:reporter) { create(:user) }
+
+  before do
+    # public project
+    project.public = true
+    project.save!
+
+    # full access
+    project.team << [master, :master]
+
+    # readonly
+    project.team << [reporter, :reporter]
+
+  end
+
+  describe "Project should be public" do
+    subject { project }
+
+    its(:public?) { should be_true }
+  end
+
+  describe "GET /:project_path" do
+    subject { project_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/tree/master" do
+    subject { project_tree_path(project, project.repository.root_ref) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/commits/master" do
+    subject { project_commits_path(project, project.repository.root_ref, limit: 1) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/commit/:sha" do
+    subject { project_commit_path(project, project.repository.commit) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/compare" do
+    subject { project_compare_index_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/team" do
+    subject { project_team_index_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/wall" do
+    subject { project_wall_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/blob" do
+    before do
+      commit = project.repository.commit
+      path = commit.tree.contents.select { |i| i.is_a?(Grit::Blob) }.first.name
+      @blob_path = project_blob_path(project, File.join(commit.id, path))
+    end
+
+    it { @blob_path.should be_allowed_for master }
+    it { @blob_path.should be_allowed_for reporter }
+    it { @blob_path.should be_allowed_for :admin }
+    it { @blob_path.should be_allowed_for guest }
+    it { @blob_path.should be_allowed_for :user }
+    it { @blob_path.should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/edit" do
+    subject { edit_project_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/deploy_keys" do
+    subject { project_deploy_keys_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/issues" do
+    subject { project_issues_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/snippets" do
+    subject { project_snippets_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/snippets/new" do
+    subject { new_project_snippet_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/merge_requests" do
+    subject { project_merge_requests_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/merge_requests/new" do
+    subject { new_project_merge_request_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/branches/recent" do
+    subject { recent_project_branches_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/branches" do
+    subject { project_branches_path(project) }
+
+    before do
+      # Speed increase
+      Project.any_instance.stub(:branches).and_return([])
+    end
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/tags" do
+    subject { project_tags_path(project) }
+
+    before do
+      # Speed increase
+      Project.any_instance.stub(:tags).and_return([])
+    end
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/hooks" do
+    subject { project_hooks_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+end
diff --git a/spec/features/security/project_access_spec.rb b/spec/features/security/project_access_spec.rb
deleted file mode 100644
index d0964a947db..00000000000
--- a/spec/features/security/project_access_spec.rb
+++ /dev/null
@@ -1,474 +0,0 @@
-require 'spec_helper'
-
-describe "Application access" do
-  describe "GET /" do
-    it { root_path.should be_allowed_for :admin }
-    it { root_path.should be_allowed_for :user }
-    it { root_path.should be_denied_for :visitor }
-  end
-
-  describe "GET /projects/new" do
-    it { new_project_path.should be_allowed_for :admin }
-    it { new_project_path.should be_allowed_for :user }
-    it { new_project_path.should be_denied_for :visitor }
-  end
-
-  describe "Project" do
-    let(:project) { create(:project_with_code) }
-
-    let(:master) { create(:user) }
-    let(:guest) { create(:user) }
-    let(:reporter) { create(:user) }
-
-    before do
-      # full access
-      project.team << [master, :master]
-
-      # readonly
-      project.team << [reporter, :reporter]
-    end
-
-    describe "GET /project_code" do
-      subject { project_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/tree/master" do
-      subject { project_tree_path(project, project.repository.root_ref) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/commits/master" do
-      subject { project_commits_path(project, project.repository.root_ref, limit: 1) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/commit/:sha" do
-      subject { project_commit_path(project, project.repository.commit) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/compare" do
-      subject { project_compare_index_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/team" do
-      subject { project_team_index_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/wall" do
-      subject { project_wall_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/blob" do
-      before do
-        commit = project.repository.commit
-        path = commit.tree.contents.select { |i| i.is_a?(Grit::Blob) }.first.name
-        @blob_path = project_blob_path(project, File.join(commit.id, path))
-      end
-
-      it { @blob_path.should be_allowed_for master }
-      it { @blob_path.should be_allowed_for reporter }
-      it { @blob_path.should be_allowed_for :admin }
-      it { @blob_path.should be_denied_for guest }
-      it { @blob_path.should be_denied_for :user }
-      it { @blob_path.should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/edit" do
-      subject { edit_project_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_denied_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/deploy_keys" do
-      subject { project_deploy_keys_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_denied_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/issues" do
-      subject { project_issues_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/snippets" do
-      subject { project_snippets_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/merge_requests" do
-      subject { project_merge_requests_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/branches/recent" do
-      subject { recent_project_branches_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/branches" do
-      subject { project_branches_path(project) }
-
-      before do
-        # Speed increase
-        Project.any_instance.stub(:branches).and_return([])
-      end
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/tags" do
-      subject { project_tags_path(project) }
-
-      before do
-        # Speed increase
-        Project.any_instance.stub(:tags).and_return([])
-      end
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/hooks" do
-      subject { project_hooks_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-  end
-
-
-  describe "PublicProject" do
-    let(:project) { create(:project_with_code) }
-
-    let(:master) { create(:user) }
-    let(:guest) { create(:user) }
-    let(:reporter) { create(:user) }
-
-    let(:admin) { create(:user) }
-
-    before do
-      # public project
-      project.public = true
-      project.save!
-
-      # full access
-      project.team << [master, :master]
-
-      # readonly
-      project.team << [reporter, :reporter]
-
-    end
-
-    describe "Project should be public" do
-      subject { project }
-
-      its(:public?) { should be_true }
-    end
-
-    describe "GET /project_code" do
-      subject { project_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/tree/master" do
-      subject { project_tree_path(project, project.repository.root_ref) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/commits/master" do
-      subject { project_commits_path(project, project.repository.root_ref, limit: 1) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/commit/:sha" do
-      subject { project_commit_path(project, project.repository.commit) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/compare" do
-      subject { project_compare_index_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/team" do
-      subject { project_team_index_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/wall" do
-      subject { project_wall_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/blob" do
-      before do
-        commit = project.repository.commit
-        path = commit.tree.contents.select { |i| i.is_a?(Grit::Blob) }.first.name
-        @blob_path = project_blob_path(project, File.join(commit.id, path))
-      end
-
-      it { @blob_path.should be_allowed_for master }
-      it { @blob_path.should be_allowed_for reporter }
-      it { @blob_path.should be_allowed_for :admin }
-      it { @blob_path.should be_allowed_for guest }
-      it { @blob_path.should be_allowed_for :user }
-      it { @blob_path.should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/edit" do
-      subject { edit_project_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_denied_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/deploy_keys" do
-      subject { project_deploy_keys_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_denied_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/issues" do
-      subject { project_issues_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/snippets" do
-      subject { project_snippets_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/snippets/new" do
-      subject { new_project_snippet_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/merge_requests" do
-      subject { project_merge_requests_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/branches/recent" do
-      subject { recent_project_branches_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/branches" do
-      subject { project_branches_path(project) }
-
-      before do
-        # Speed increase
-        Project.any_instance.stub(:branches).and_return([])
-      end
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/tags" do
-      subject { project_tags_path(project) }
-
-      before do
-        # Speed increase
-        Project.any_instance.stub(:tags).and_return([])
-      end
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/hooks" do
-      subject { project_hooks_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-  end
-end
-- 
GitLab


From 7a0ad959ea2556aa3cf211b8e4f2d83ae245f83c Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 25 Sep 2013 14:04:16 +0300
Subject: [PATCH 147/248] Dashboard security specs

---
 .../security/dashboard_access_spec.rb         | 55 +++++++++++++++++++
 1 file changed, 55 insertions(+)
 create mode 100644 spec/features/security/dashboard_access_spec.rb

diff --git a/spec/features/security/dashboard_access_spec.rb b/spec/features/security/dashboard_access_spec.rb
new file mode 100644
index 00000000000..adec5926c6f
--- /dev/null
+++ b/spec/features/security/dashboard_access_spec.rb
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe "Dashboard access" do
+  describe "GET /dashboard" do
+    subject { dashboard_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /dashboard/issues" do
+    subject { issues_dashboard_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /dashboard/merge_requests" do
+    subject { merge_requests_dashboard_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /dashboard/projects" do
+    subject { projects_dashboard_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /help" do
+    subject { help_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /projects/new" do
+    it { new_project_path.should be_allowed_for :admin }
+    it { new_project_path.should be_allowed_for :user }
+    it { new_project_path.should be_denied_for :visitor }
+  end
+
+  describe "GET /groups/new" do
+    it { new_group_path.should be_allowed_for :admin }
+    it { new_group_path.should be_allowed_for :user }
+    it { new_group_path.should be_denied_for :visitor }
+  end
+end
-- 
GitLab


From af900330e3cc28d9559399c1efabf37774867ea3 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 25 Sep 2013 14:04:32 +0300
Subject: [PATCH 148/248] Version up to 6.2.0.pre

---
 VERSION | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/VERSION b/VERSION
index dfda3e0b4f0..79e046f49a5 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-6.1.0
+6.2.0.pre
-- 
GitLab


From 3b5b715d072f1a2ed7678f4d7331d52f3904b933 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 25 Sep 2013 14:05:03 +0300
Subject: [PATCH 149/248] Extend profile security specs

---
 spec/features/security/profile_access_spec.rb | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/spec/features/security/profile_access_spec.rb b/spec/features/security/profile_access_spec.rb
index 52130b3f8c6..7754b28347a 100644
--- a/spec/features/security/profile_access_spec.rb
+++ b/spec/features/security/profile_access_spec.rb
@@ -45,5 +45,32 @@ describe "Users Security" do
       it { should be_allowed_for :user }
       it { should be_denied_for :visitor }
     end
+
+    describe "GET /profile/history" do
+      subject { history_profile_path }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for :user }
+      it { should be_denied_for :visitor }
+    end
+
+    describe "GET /profile/notifications" do
+      subject { profile_notifications_path }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for :user }
+      it { should be_denied_for :visitor }
+    end
+
+    describe "GET /profile/groups" do
+      subject { profile_groups_path }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for :user }
+      it { should be_denied_for :visitor }
+    end
   end
 end
-- 
GitLab


From 09987ec78ce41ae0161fe419b2220d8d9c223cf7 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 25 Sep 2013 14:05:35 +0300
Subject: [PATCH 150/248] Modify permissions for project and group

* Hooks and team pages allowed only for masters/owners
* Group page allowed for admin
* Corrent authentication for Projects controller
* Hide some project elements from visitor
---
 app/controllers/projects/hooks_controller.rb  |  3 +-
 .../projects/snippets_controller.rb           |  2 -
 .../projects/team_members_controller.rb       |  3 +-
 app/controllers/projects_controller.rb        |  6 +-
 app/models/ability.rb                         |  2 +-
 app/models/group.rb                           |  4 ++
 app/views/projects/_clone_panel.html.haml     | 67 ++++++++++---------
 7 files changed, 44 insertions(+), 43 deletions(-)

diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb
index 3367ddb5d14..1a94dbab5ea 100644
--- a/app/controllers/projects/hooks_controller.rb
+++ b/app/controllers/projects/hooks_controller.rb
@@ -1,7 +1,6 @@
 class Projects::HooksController < Projects::ApplicationController
   # Authorize
-  before_filter :authorize_read_project!
-  before_filter :authorize_admin_project!, only: [:new, :create, :destroy]
+  before_filter :authorize_admin_project!
 
   respond_to :html
 
diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
index 59063103ecb..dd0c1a57089 100644
--- a/app/controllers/projects/snippets_controller.rb
+++ b/app/controllers/projects/snippets_controller.rb
@@ -14,8 +14,6 @@ class Projects::SnippetsController < Projects::ApplicationController
   # Allow destroy snippet
   before_filter :authorize_admin_project_snippet!, only: [:destroy]
 
-  layout 'projects'
-
   respond_to :html
 
   def index
diff --git a/app/controllers/projects/team_members_controller.rb b/app/controllers/projects/team_members_controller.rb
index 6fee770cae2..b4b318fa59e 100644
--- a/app/controllers/projects/team_members_controller.rb
+++ b/app/controllers/projects/team_members_controller.rb
@@ -1,7 +1,6 @@
 class Projects::TeamMembersController < Projects::ApplicationController
   # Authorize
-  before_filter :authorize_read_project!
-  before_filter :authorize_admin_project!, except: [:index, :show]
+  before_filter :authorize_admin_project!
 
   layout "project_settings"
 
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index f31fb666e3e..7264128691e 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -1,7 +1,7 @@
-class ProjectsController < Projects::ApplicationController
+class ProjectsController < ApplicationController
   skip_before_filter :authenticate_user!, only: [:show]
-  skip_before_filter :project, only: [:new, :create]
-  skip_before_filter :repository, only: [:new, :create]
+  before_filter :project, except: [:new, :create]
+  before_filter :repository, except: [:new, :create]
 
   # Authorize
   before_filter :authorize_read_project!, except: [:index, :new, :create]
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 26988c5e6a7..ad070dad296 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -154,7 +154,7 @@ class Ability
     def group_abilities user, group
       rules = []
 
-      if group.users.include?(user)
+      if group.users.include?(user) || user.admin?
         rules << :read_group
       end
 
diff --git a/app/models/group.rb b/app/models/group.rb
index fce8d71217b..0b36c934375 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -32,6 +32,10 @@ class Group < Namespace
     end
   end
 
+  def add_user(user, group_access)
+    self.users_groups.create(user_id: user.id, group_access: group_access)
+  end
+
   def change_owner(user)
     self.owner = user
     membership = users_groups.where(user_id: user.id).first
diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml
index c5ab64505c6..c2f85e8ebe8 100644
--- a/app/views/projects/_clone_panel.html.haml
+++ b/app/views/projects/_clone_panel.html.haml
@@ -19,37 +19,38 @@
               %i.icon-download-alt
               %span.only-wide Download
 
-        .dropdown.pull-right
-          %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
-            %i.icon-plus-sign-alt
-            %span.only-wide New
-            %b.caret
-          %ul.dropdown-menu
-            - if @project.issues_enabled && can?(current_user, :write_issue, @project)
-              %li
-                = link_to url_for_new_issue, title: "New Issue" do
-                  Issue
-            - if @project.merge_requests_enabled && can?(current_user, :write_merge_request, @project)
-              %li
-                = link_to new_project_merge_request_path(@project), title: "New Merge Request" do
-                  Merge Request
-            - if @project.snippets_enabled && can?(current_user, :write_snippet, @project)
-              %li
-                = link_to new_project_snippet_path(@project), title: "New Snippet" do
-                  Snippet
-            - if can? current_user, :push_code, @project
-              %li.divider
-              %li
-                = link_to new_project_branch_path(@project) do
-                  %i.icon-code-fork
-                  Git branch
-              %li
-                = link_to new_project_tag_path(@project) do
-                  %i.icon-tag
-                  Git tag
+        - if current_user
+          .dropdown.pull-right
+            %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
+              %i.icon-plus-sign-alt
+              %span.only-wide New
+              %b.caret
+            %ul.dropdown-menu
+              - if @project.issues_enabled && can?(current_user, :write_issue, @project)
+                %li
+                  = link_to url_for_new_issue, title: "New Issue" do
+                    Issue
+              - if @project.merge_requests_enabled && can?(current_user, :write_merge_request, @project)
+                %li
+                  = link_to new_project_merge_request_path(@project), title: "New Merge Request" do
+                    Merge Request
+              - if @project.snippets_enabled && can?(current_user, :write_snippet, @project)
+                %li
+                  = link_to new_project_snippet_path(@project), title: "New Snippet" do
+                    Snippet
+              - if can? current_user, :push_code, @project
+                %li.divider
+                %li
+                  = link_to new_project_branch_path(@project) do
+                    %i.icon-code-fork
+                    Git branch
+                %li
+                  = link_to new_project_tag_path(@project) do
+                    %i.icon-tag
+                    Git tag
 
-            - if can?(current_user, :admin_team_member, @project)
-              %li.divider
-              %li
-                = link_to new_project_team_member_path(@project), title: "New project member" do
-                  Project member
+              - if can?(current_user, :admin_team_member, @project)
+                %li.divider
+                %li
+                  = link_to new_project_team_member_path(@project), title: "New project member" do
+                    Project member
-- 
GitLab


From a0e6ad83d1c02879bd8fe88f65e95fd3a54536ef Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 25 Sep 2013 14:23:06 +0300
Subject: [PATCH 151/248] Fix public project tests

---
 features/steps/public/projects_feature.rb | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/features/steps/public/projects_feature.rb b/features/steps/public/projects_feature.rb
index 2f2c4de0b2a..e9a4d56e36b 100644
--- a/features/steps/public/projects_feature.rb
+++ b/features/steps/public/projects_feature.rb
@@ -11,7 +11,6 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps
 
   step 'I should see project "Empty Public Project"' do
     page.should have_content "Empty Public Project"
-    puts page.save_page('foo.html')
   end
 
   step 'I should see public project details' do
@@ -24,7 +23,7 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps
   end
 
   step 'public project "Community"' do
-    create :project_with_code, name: 'Community', public: true
+    create :project_with_code, name: 'Community', public: true, default_branch: 'master'
   end
 
   step 'public empty project "Empty Public Project"' do
-- 
GitLab


From ec640cf695373413ad6f8e1ffee20cf7836a1ec4 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 25 Sep 2013 15:49:35 +0300
Subject: [PATCH 152/248] Mention public projects in CHANGELOG

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

diff --git a/CHANGELOG b/CHANGELOG
index e955925138c..3db03f76ed7 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+v 6.2.0
+  - Public projects are visible from the outside
+
 v 6.1.0
   - Project specific IDs for issues, mr, milestones
     Above items will get a new id and for example all bookmarked issue urls will change.
-- 
GitLab


From 7e0c4af2cd086f0fce4ee7cd8baf42180e7ed186 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 25 Sep 2013 16:54:36 +0300
Subject: [PATCH 153/248] Hide some filters if current_user is nil

---
 app/views/shared/_project_filter.html.haml | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/app/views/shared/_project_filter.html.haml b/app/views/shared/_project_filter.html.haml
index 5e0f503c819..f3d032ef986 100644
--- a/app/views/shared/_project_filter.html.haml
+++ b/app/views/shared/_project_filter.html.haml
@@ -1,15 +1,16 @@
 = form_tag project_entities_path, method: 'get' do
   %fieldset
-    %ul.nav.nav-pills.nav-stacked
-      %li{class: ("active" if params[:scope].blank?)}
-        = link_to project_filter_path(scope: nil) do
-          Everyone's
-      %li{class: ("active" if params[:scope] == 'assigned-to-me')}
-        = link_to project_filter_path(scope: 'assigned-to-me') do
-          Assigned to me
-      %li{class: ("active" if params[:scope] == 'created-by-me')}
-        = link_to project_filter_path(scope: 'created-by-me') do
-          Created by me
+    - if current_user
+      %ul.nav.nav-pills.nav-stacked
+        %li{class: ("active" if params[:scope].blank?)}
+          = link_to project_filter_path(scope: nil) do
+            Everyone's
+        %li{class: ("active" if params[:scope] == 'assigned-to-me')}
+          = link_to project_filter_path(scope: 'assigned-to-me') do
+            Assigned to me
+        %li{class: ("active" if params[:scope] == 'created-by-me')}
+          = link_to project_filter_path(scope: 'created-by-me') do
+            Created by me
 
     %ul.nav.nav-pills.nav-stacked
       %li{class: ("active" if params[:state].blank?)}
-- 
GitLab


From 07309d690aa85efbed5009ba1103336ea251d5fd Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 25 Sep 2013 16:59:38 +0300
Subject: [PATCH 154/248] Tree files use normal font-weight

---
 app/views/projects/tree/_blob_item.html.haml      | 2 +-
 app/views/projects/tree/_submodule_item.html.haml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/views/projects/tree/_blob_item.html.haml b/app/views/projects/tree/_blob_item.html.haml
index ec15b608f85..b179ad7d245 100644
--- a/app/views/projects/tree/_blob_item.html.haml
+++ b/app/views/projects/tree/_blob_item.html.haml
@@ -1,7 +1,7 @@
 %tr{ class: "tree-item #{tree_hex_class(blob_item)}" }
   %td.tree-item-file-name
     = tree_icon(type)
-    %strong= link_to truncate(blob_item.name, length: 40), project_blob_path(@project, tree_join(@id || @commit.id, blob_item.name))
+    %span= link_to truncate(blob_item.name, length: 40), project_blob_path(@project, tree_join(@id || @commit.id, blob_item.name))
   %td.tree_time_ago.cgray
     %span.log_loading.hide
       Loading commit data...
diff --git a/app/views/projects/tree/_submodule_item.html.haml b/app/views/projects/tree/_submodule_item.html.haml
index 092a024afbc..26aad16e2c0 100644
--- a/app/views/projects/tree/_submodule_item.html.haml
+++ b/app/views/projects/tree/_submodule_item.html.haml
@@ -4,7 +4,7 @@
 %tr{ class: "tree-item", url: url }
   %td.tree-item-file-name
     = image_tag "submodule.png"
-    %strong= truncate(name, length: 40)
+    %span= truncate(name, length: 40)
   %td
     %code= submodule_item.id[0..10]
   %td{ colspan: 2 }
-- 
GitLab


From d09345d12ec7b98026f4c959928798c88cd94fc8 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 25 Sep 2013 17:20:07 +0300
Subject: [PATCH 155/248] Fixed styling for delete button of snippet

---
 app/views/projects/snippets/_form.html.haml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/app/views/projects/snippets/_form.html.haml b/app/views/projects/snippets/_form.html.haml
index e83f5d0d65d..d414ee2d1ec 100644
--- a/app/views/projects/snippets/_form.html.haml
+++ b/app/views/projects/snippets/_form.html.haml
@@ -31,10 +31,10 @@
         = f.submit 'Create snippet', class: "btn-create btn"
       - else
         = f.submit 'Save', class: "btn-save btn"
-      = link_to "Cancel", project_snippets_path(@project), class: " btn btn-cancel"
-      - unless @snippet.new_record?
-        .pull-right= link_to 'Destroy', project_snippet_path(@project, @snippet), confirm: 'Are you sure?', method: :delete, class: "btn pull-right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
+      = link_to "Cancel", project_snippets_path(@project), class: "btn btn-cancel"
 
+    - unless @snippet.new_record?
+      = link_to 'Remove snippet', project_snippet_path(@project, @snippet), confirm: 'Are you sure?', method: :delete, class: "btn pull-right btn-remove delete-snippet prepend-left-10", id: "destroy_snippet_#{@snippet.id}"
 
 :javascript
   var editor = ace.edit("editor");
-- 
GitLab


From 14c5e24a909a06c47e8ff69192e99df761a8b773 Mon Sep 17 00:00:00 2001
From: Johannes Becker <jb@jbecker.it>
Date: Wed, 25 Sep 2013 16:49:39 +0200
Subject: [PATCH 156/248] Added spinach Tests for pivotaltracker service

---
 features/project/service.feature           |  6 ++++++
 features/steps/project/project_services.rb | 14 ++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/features/project/service.feature b/features/project/service.feature
index 6bb0c3e2c57..e685c385d1d 100644
--- a/features/project/service.feature
+++ b/features/project/service.feature
@@ -18,3 +18,9 @@ Feature: Project Services
     And I click hipchat service link
     And I fill hipchat settings
     Then I should see hipchat service settings saved
+
+  Scenario: Activate pivotaltracker service
+    When I visit project "Shop" services page
+    And I click pivotaltracker service link
+    And I fill pivotaltracker settings
+    Then I should see pivotaltracker service settings saved
diff --git a/features/steps/project/project_services.rb b/features/steps/project/project_services.rb
index 10feb8ea8be..a24100ff8c0 100644
--- a/features/steps/project/project_services.rb
+++ b/features/steps/project/project_services.rb
@@ -44,4 +44,18 @@ class ProjectServices < Spinach::FeatureSteps
     find_field('Room').value.should == 'gitlab'
   end
 
+
+  And 'I click pivotaltracker service link' do
+    click_link 'PivotalTracker'
+  end
+
+  And 'I fill pivotaltracker settings' do
+    check 'Active'
+    fill_in 'Token', with: 'verySecret'
+    click_button 'Save'
+  end
+
+  Then 'I should see pivotaltracker service settings saved' do
+    find_field('Token').value.should == 'verySecret'
+  end
 end
-- 
GitLab


From 93ae686f4568031ec41743b354deb81ccf487e38 Mon Sep 17 00:00:00 2001
From: Johannes Becker <jb@jbecker.it>
Date: Wed, 25 Sep 2013 16:54:34 +0200
Subject: [PATCH 157/248] Syntax cleanup

---
 app/models/pivotaltracker_service.rb | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/app/models/pivotaltracker_service.rb b/app/models/pivotaltracker_service.rb
index 4efdafa9791..f28e142da77 100644
--- a/app/models/pivotaltracker_service.rb
+++ b/app/models/pivotaltracker_service.rb
@@ -38,18 +38,22 @@ class PivotaltrackerService < Service
   def execute(push)
     url = 'https://www.pivotaltracker.com/services/v5/source_commits'
     push[:commits].each do |commit|
-      message = {'source_commit' =>
-                  {'commit_id' => commit[:id],
-                   'author' => commit[:author][:name],
-                   'url' => commit[:url],
-                   'message' => commit[:message]}
-                }
-      status = PivotaltrackerService.post(url,
-                     body: message.to_json,
-                     headers: {'Content-Type' => 'application/json',
-                               'X-TrackerToken' => token}
-                    )
+      message = {
+        'source_commit' => {
+          'commit_id' => commit[:id],
+          'author' => commit[:author][:name],
+          'url' => commit[:url],
+          'message' => commit[:message]
+        }
+      }
+      PivotaltrackerService.post(
+        url,
+        body: message.to_json,
+        headers: {
+          'Content-Type' => 'application/json',
+          'X-TrackerToken' => token
+        }
+      )
     end
   end
-
 end
-- 
GitLab


From 38c019cd0ce3153fa097d69b336a9a2f9a4c0247 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 25 Sep 2013 18:26:54 +0300
Subject: [PATCH 158/248] Hide new issue button if not authorized

---
 app/views/projects/issues/show.html.haml | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index d36a831432d..6d1a088721c 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -6,9 +6,10 @@
     = @issue.created_at.stamp("Aug 21, 2011")
 
   %span.pull-right
-    = link_to new_project_issue_path(@project), class: "btn grouped", title: "New Issue", id: "new_issue_link" do
-      %i.icon-plus
-      New Issue
+    - if can?(current_user, :write_issue, @project)
+      = link_to new_project_issue_path(@project), class: "btn grouped", title: "New Issue", id: "new_issue_link" do
+        %i.icon-plus
+        New Issue
     - if can?(current_user, :modify_issue, @issue)
       - if @issue.closed?
         = link_to 'Reopen', project_issue_path(@project, @issue, issue: {state_event: :reopen }, status_only: true), method: :put,  class: "btn grouped reopen_issue"
-- 
GitLab


From 468ce289bf83ac8664653a554eb8101fd4e6a28b Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Tue, 24 Sep 2013 23:12:31 +0200
Subject: [PATCH 159/248] Enable rack attack and add a throttle.

---
 config/application.rb              | 3 +++
 config/initializers/rack_attack.rb | 3 +++
 2 files changed, 6 insertions(+)
 create mode 100644 config/initializers/rack_attack.rb

diff --git a/config/application.rb b/config/application.rb
index 8ac07ef337a..6ddc87010b3 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -77,5 +77,8 @@ module Gitlab
     # 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT']
     #
     # config.relative_url_root = "/gitlab"
+
+    # Enable rack attack middleware
+    config.middleware.use Rack::Attack
   end
 end
diff --git a/config/initializers/rack_attack.rb b/config/initializers/rack_attack.rb
new file mode 100644
index 00000000000..88e638ba118
--- /dev/null
+++ b/config/initializers/rack_attack.rb
@@ -0,0 +1,3 @@
+Rack::Attack.throttle('user logins, registration and password reset', limit: 6, period: 60.seconds) do |req|
+  req.ip if ["/users/password", "/users/sign_in", "/users"].include?(req.path) && req.post?
+end
-- 
GitLab


From fc25a210733aca557658743102a15062248e8dd1 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 25 Sep 2013 21:33:35 +0300
Subject: [PATCH 160/248] Fix remove snippet test

---
 features/project/snippets.feature          | 2 +-
 features/steps/project/project_snippets.rb | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/features/project/snippets.feature b/features/project/snippets.feature
index a26c8dc8474..dfaa02663a0 100644
--- a/features/project/snippets.feature
+++ b/features/project/snippets.feature
@@ -31,5 +31,5 @@ Feature: Project Snippets
   Scenario: I destroy "Snippet one"
     Given I visit snippet page "Snippet one"
     And I click link "Edit"
-    And I click link "Destroy"
+    And I click link "Remove Snippet"
     Then I should not see "Snippet one" in snippets
diff --git a/features/steps/project/project_snippets.rb b/features/steps/project/project_snippets.rb
index 86c0685256a..5082b31198a 100644
--- a/features/steps/project/project_snippets.rb
+++ b/features/steps/project/project_snippets.rb
@@ -47,8 +47,8 @@ class ProjectSnippets < Spinach::FeatureSteps
     end
   end
 
-  And 'I click link "Destroy"' do
-    click_link "Destroy"
+  And 'I click link "Remove Snippet"' do
+    click_link "Remove snippet"
   end
 
   And 'I submit new snippet "Snippet three"' do
-- 
GitLab


From 01fdff2d754694fe413fd74c348391d15b982d64 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 26 Sep 2013 10:02:18 +0300
Subject: [PATCH 161/248] Group has multiple owners so no sense to show one at
 dashboard list

---
 app/assets/stylesheets/sections/dashboard.scss | 10 ++++++++--
 app/views/dashboard/_groups.html.haml          |  3 ---
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/app/assets/stylesheets/sections/dashboard.scss b/app/assets/stylesheets/sections/dashboard.scss
index 61331cee413..3f7825d71ce 100644
--- a/app/assets/stylesheets/sections/dashboard.scss
+++ b/app/assets/stylesheets/sections/dashboard.scss
@@ -85,12 +85,18 @@
     color: #666;
   }
 
-  .last-activity, .owner-info {
+  .last-activity {
     color: #AAA;
     display: block;
     margin-top: 5px;
-    .date, .owner {
+    .date {
       color: #777;
     }
   }
 }
+
+.group-row {
+  .arrow {
+    padding: 2px 5px;
+  }
+}
diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml
index 8b32c5642bb..b4f3866228d 100644
--- a/app/views/dashboard/_groups.html.haml
+++ b/app/views/dashboard/_groups.html.haml
@@ -14,9 +14,6 @@
             = truncate(group.name, length: 35)
           %span.arrow
             %i.icon-angle-right
-          %span.owner-info
-            %span Owner:
-            %span.owner= group.owner_name
     - if groups.blank?
       %li
         %h3.nothing_here_message You have no groups yet.
-- 
GitLab


From dd743e20e5b197cf8b393d0d50b17d1e4557c069 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 26 Sep 2013 10:28:43 +0300
Subject: [PATCH 162/248] Group owner or admin can remove other group owners

---
 app/controllers/users_groups_controller.rb    | 2 +-
 app/views/users_groups/_users_group.html.haml | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/app/controllers/users_groups_controller.rb b/app/controllers/users_groups_controller.rb
index df13b86fdcd..749da1e1413 100644
--- a/app/controllers/users_groups_controller.rb
+++ b/app/controllers/users_groups_controller.rb
@@ -19,7 +19,7 @@ class UsersGroupsController < ApplicationController
 
   def destroy
     @users_group = @group.users_groups.find(params[:id])
-    @users_group.destroy unless @users_group.user == @group.owner
+    @users_group.destroy
 
     respond_to do |format|
       format.html { redirect_to members_group_path(@group), notice: 'User was  successfully removed from group.' }
diff --git a/app/views/users_groups/_users_group.html.haml b/app/views/users_groups/_users_group.html.haml
index c8d306838f7..5cdb5bb8c40 100644
--- a/app/views/users_groups/_users_group.html.haml
+++ b/app/views/users_groups/_users_group.html.haml
@@ -10,7 +10,7 @@
   %span.pull-right
     %strong= member.human_access
 
-    - if show_controls && user != @group.owner && user != current_user
+    - if show_controls && can?(current_user, :manage_group, @group) && current_user != user
       = link_to '#', class: "btn-tiny btn js-toggle-button", title: 'Edit access level' do
         %i.icon-edit
       = link_to group_users_group_path(@group, member), confirm: remove_user_from_group_message(@group, user), method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
@@ -20,4 +20,4 @@
     = form_for [@group, member], remote: true do |f|
       .alert.prepend-top-20
         = f.select :group_access, options_for_select(UsersGroup.group_access_roles, member.group_access)
-        = f.submit 'Save', class: 'btn btn-save'
+        = f.submit 'Save', class: 'btn btn-save btn-small'
-- 
GitLab


From 02bb17d80fc04a1d633599494b8d5f6b8b86882f Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 26 Sep 2013 10:33:06 +0300
Subject: [PATCH 163/248] Remove project transfer page since we already have
 multiple owners for group

---
 app/controllers/groups_controller.rb | 10 +---------
 app/views/groups/edit.html.haml      | 13 -------------
 2 files changed, 1 insertion(+), 22 deletions(-)

diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 9dc9afe9e67..caf8ef85e87 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -73,15 +73,7 @@ class GroupsController < ApplicationController
   end
 
   def update
-    group_params = params[:group].dup
-    owner_id = group_params.delete(:owner_id)
-
-    if owner_id
-      @group.owner = User.find(owner_id)
-      @group.save
-    end
-
-    if @group.update_attributes(group_params)
+    if @group.update_attributes(params[:group])
       redirect_to @group, notice: 'Group was successfully updated.'
     else
       render action: "edit"
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index 8aefdf7f513..2682d31ff47 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -9,8 +9,6 @@
         = link_to '#tab-projects', 'data-toggle' => 'tab' do
           %i.icon-folder-close
           Projects
-      %li
-        = link_to 'Transfer', '#tab-transfer', 'data-toggle' => 'tab'
       %li
         = link_to 'Remove', '#tab-remove', 'data-toggle' => 'tab'
 
@@ -65,17 +63,6 @@
             - if @group.projects.blank?
               %p.nothing_here_message This group has no projects yet
 
-      .tab-pane#tab-transfer
-        .ui-box.ui-box-danger
-          .title Transfer group
-          .ui-box-body
-            %p
-              Transferring group will cause loss of admin control over group and all child projects
-            = form_for @group do |f|
-              = users_select_tag(:'group[owner_id]')
-              %hr
-              = f.submit 'Transfer group', class: "btn btn-small btn-remove"
-
       .tab-pane#tab-remove
         .ui-box.ui-box-danger
           .title Remove group
-- 
GitLab


From e8de21fb7737ce6b1ada57a8e251a6c968184529 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 26 Sep 2013 14:48:58 +0300
Subject: [PATCH 164/248] Namespaces.owner_id can be null

---
 db/migrate/20130926081215_change_owner_id_for_group.rb | 9 +++++++++
 db/schema.rb                                           | 4 ++--
 2 files changed, 11 insertions(+), 2 deletions(-)
 create mode 100644 db/migrate/20130926081215_change_owner_id_for_group.rb

diff --git a/db/migrate/20130926081215_change_owner_id_for_group.rb b/db/migrate/20130926081215_change_owner_id_for_group.rb
new file mode 100644
index 00000000000..8f1992c37ab
--- /dev/null
+++ b/db/migrate/20130926081215_change_owner_id_for_group.rb
@@ -0,0 +1,9 @@
+class ChangeOwnerIdForGroup < ActiveRecord::Migration
+  def up
+    change_column :namespaces, :owner_id, :integer, null: true
+  end
+
+  def down
+    change_column :namespaces, :owner_id, :integer, null: false
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index d5effe40ea1..713d9f733d6 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 => 20130909132950) do
+ActiveRecord::Schema.define(:version => 20130926081215) do
 
   create_table "deploy_keys_projects", :force => true do |t|
     t.integer  "deploy_key_id", :null => false
@@ -129,7 +129,7 @@ ActiveRecord::Schema.define(:version => 20130909132950) do
   create_table "namespaces", :force => true do |t|
     t.string   "name",                        :null => false
     t.string   "path",                        :null => false
-    t.integer  "owner_id",                    :null => false
+    t.integer  "owner_id"
     t.datetime "created_at",                  :null => false
     t.datetime "updated_at",                  :null => false
     t.string   "type"
-- 
GitLab


From 66d539d2352f88b30bc58550b26ddc72b1d7916d Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 26 Sep 2013 14:49:22 +0300
Subject: [PATCH 165/248] Group ownership completely based on users_groups
 relation now

Before we have only owner_id to determine group owner
With multiple owners per group we should get rid of owner_id in group.
So from now @group.owner will always be nil but
@group.owners return an actual array of users who can admin this group
---
 app/controllers/admin/groups_controller.rb    | 11 ++------
 app/controllers/groups_controller.rb          |  2 +-
 app/controllers/profiles/groups_controller.rb |  4 +--
 app/models/ability.rb                         |  4 +--
 app/models/group.rb                           | 25 ++++++++-----------
 app/models/namespace.rb                       |  2 +-
 app/models/project.rb                         | 10 +++-----
 app/models/user.rb                            |  2 +-
 app/services/system_hooks_service.rb          |  6 +++--
 app/views/admin/groups/index.html.haml        |  7 ++----
 app/views/admin/groups/show.html.haml         | 23 ++---------------
 app/views/admin/projects/show.html.haml       |  2 +-
 12 files changed, 32 insertions(+), 66 deletions(-)

diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index a2201f732e6..89b395786b3 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -20,9 +20,9 @@ class Admin::GroupsController < Admin::ApplicationController
   def create
     @group = Group.new(params[:group])
     @group.path = @group.name.dup.parameterize if @group.name
-    @group.owner = current_user
 
     if @group.save
+      @group.add_owner(current_user)
       redirect_to [:admin, @group], notice: 'Group was successfully created.'
     else
       render "new"
@@ -30,14 +30,7 @@ class Admin::GroupsController < Admin::ApplicationController
   end
 
   def update
-    group_params = params[:group].dup
-    owner_id =group_params.delete(:owner_id)
-
-    if owner_id
-      @group.change_owner(User.find(owner_id))
-    end
-
-    if @group.update_attributes(group_params)
+    if @group.update_attributes(params[:group])
       redirect_to [:admin, @group], notice: 'Group was successfully updated.'
     else
       render "edit"
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index caf8ef85e87..f80167da4cb 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -21,9 +21,9 @@ class GroupsController < ApplicationController
   def create
     @group = Group.new(params[:group])
     @group.path = @group.name.dup.parameterize if @group.name
-    @group.owner = current_user
 
     if @group.save
+      @group.add_owner(current_user)
       redirect_to @group, notice: 'Group was successfully created.'
     else
       render action: "new"
diff --git a/app/controllers/profiles/groups_controller.rb b/app/controllers/profiles/groups_controller.rb
index e276d07b489..378ff6bcf34 100644
--- a/app/controllers/profiles/groups_controller.rb
+++ b/app/controllers/profiles/groups_controller.rb
@@ -8,8 +8,8 @@ class Profiles::GroupsController < ApplicationController
   def leave
     @users_group = group.users_groups.where(user_id: current_user.id).first
 
-    if group.owner == current_user
-      redirect_to(profile_groups_path, alert: "You can't leave group. You must transfer it to another owner before leaving.")
+    if group.last_owner?(current_user)
+      redirect_to(profile_groups_path, alert: "You can't leave group. You must add at least one more owner to it.")
     else
       @users_group.destroy
       redirect_to(profile_groups_path, info: "You left #{group.name} group.")
diff --git a/app/models/ability.rb b/app/models/ability.rb
index ad070dad296..85476089145 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -79,7 +79,7 @@ class Ability
         rules << project_admin_rules
       end
 
-      if project.group && project.group.owners.include?(user)
+      if project.group && project.group.has_owner?(user)
         rules << project_admin_rules
       end
 
@@ -159,7 +159,7 @@ class Ability
       end
 
       # Only group owner and administrators can manage group
-      if group.owners.include?(user) || user.admin?
+      if group.has_owner?(user) || user.admin?
         rules << [
           :manage_group,
           :manage_namespace
diff --git a/app/models/group.rb b/app/models/group.rb
index 0b36c934375..0cc3a3a0f41 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -16,14 +16,12 @@ class Group < Namespace
   has_many :users_groups, dependent: :destroy
   has_many :users, through: :users_groups
 
-  after_create :add_owner
-
   def human_name
     name
   end
 
   def owners
-    @owners ||= (users_groups.owners.map(&:user) << owner).uniq
+    @owners ||= users_groups.owners.map(&:user)
   end
 
   def add_users(user_ids, group_access)
@@ -36,20 +34,19 @@ class Group < Namespace
     self.users_groups.create(user_id: user.id, group_access: group_access)
   end
 
-  def change_owner(user)
-    self.owner = user
-    membership = users_groups.where(user_id: user.id).first
+  def add_owner(user)
+    self.add_user(user, UsersGroup::OWNER)
+  end
 
-    if membership
-      membership.update_attributes(group_access: UsersGroup::OWNER)
-    else
-      add_owner
-    end
+  def has_owner?(user)
+    owners.include?(user)
   end
 
-  private
+  def last_owner?(user)
+    has_owner?(user) && owners.size == 1
+  end
 
-  def add_owner
-    self.add_users([owner.id], UsersGroup::OWNER)
+  def members
+    users_groups
   end
 end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 18959166931..6ac94c06604 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -20,7 +20,7 @@ class Namespace < ActiveRecord::Base
   has_many :projects, dependent: :destroy
   belongs_to :owner, class_name: "User"
 
-  validates :owner, presence: true
+  validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
   validates :name, presence: true, uniqueness: true,
             length: { within: 0..255 },
             format: { with: Gitlab::Regex.name_regex,
diff --git a/app/models/project.rb b/app/models/project.rb
index 63cd3505ec4..c4f4b06713d 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -249,10 +249,10 @@ class Project < ActiveRecord::Base
   end
 
   def owner
-    if namespace
-      namespace_owner
+    if group
+      group
     else
-      creator
+      namespace.try(:owner)
     end
   end
 
@@ -276,10 +276,6 @@ class Project < ActiveRecord::Base
                              end
   end
 
-  def namespace_owner
-    namespace.try(:owner)
-  end
-
   def path_with_namespace
     if namespace
       namespace.path + '/' + path
diff --git a/app/models/user.rb b/app/models/user.rb
index ea004e4c9a7..f1f93eadc1a 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -135,7 +135,7 @@ class User < ActiveRecord::Base
       # Remove user from all groups
       user.users_groups.find_each do |membership|
         # skip owned resources
-        next if membership.group.owners.include?(user)
+        next if membership.group.last_owner?(user)
 
         return false unless membership.destroy
       end
diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb
index c872b27ba39..39aec943f75 100644
--- a/app/services/system_hooks_service.rb
+++ b/app/services/system_hooks_service.rb
@@ -23,13 +23,15 @@ class SystemHooksService
 
     case model
     when Project
+      owner = model.owner
+
       data.merge!({
         name: model.name,
         path: model.path,
         path_with_namespace: model.path_with_namespace,
         project_id: model.id,
-        owner_name: model.owner.name,
-        owner_email: model.owner.email
+        owner_name: owner.name,
+        owner_email: owner.respond_to?(:email) ?  owner.email : nil
       })
     when User
       data.merge!({
diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml
index 8e45dc76ec6..c9d7c24f204 100644
--- a/app/views/admin/groups/index.html.haml
+++ b/app/views/admin/groups/index.html.haml
@@ -31,11 +31,8 @@
 
       .clearfix.light.append-bottom-10
         %span
-          %b Owner:
-          - if group.owner
-            = link_to group.owner_name, admin_user_path(group.owner)
-          - else
-            (deleted)
+          %b Members:
+          %span.badge= group.members.size
         \|
         %span
           %b Projects:
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index 5509811bae5..1566c345809 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -24,26 +24,6 @@
           %strong
             = @group.description
 
-        %li
-          %span.light Owned by:
-          %strong
-            - if @group.owner
-              = link_to @group.owner_name, admin_user_path(@group.owner)
-            - else
-              (deleted)
-          .pull-right
-            = link_to "#", class: "btn btn-small change-owner-link" do
-              %i.icon-edit
-              Change owner
-        %li.change-owner-holder.hide.bgred
-          .form-holder
-            %strong.cred New Owner:
-            = form_for [:admin, @group] do |f|
-              = users_select_tag(:"group[owner_id]")
-              .prepend-top-10
-                = f.submit 'Change Owner', class: "btn btn-remove"
-                = link_to "Cancel", "#", class: "btn change-owner-cancel-link"
-
         %li
           %span.light Created at:
           %strong
@@ -92,4 +72,5 @@
               = link_to user.name, admin_user_path(user)
             %span.pull-right.light
               = member.human_access
-
+              = link_to group_users_group_path(@group, member), confirm: remove_user_from_group_message(@group, user), method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
+                %i.icon-minus.icon-white
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index cecc84fe093..c8a87328207 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -25,7 +25,7 @@
           %span.light Owned by:
           %strong
             - if @project.owner
-              = link_to @project.owner_name, admin_user_path(@project.owner)
+              = link_to @project.owner_name, [:admin, @project.owner]
             - else
               (deleted)
 
-- 
GitLab


From 6dfa12d05e09ed63c1aef188e02e4eae01427d0b Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 26 Sep 2013 14:52:17 +0300
Subject: [PATCH 166/248] Ignore owner_id for Group in tests

---
 features/steps/group/group.rb                 |  3 ++-
 spec/contexts/projects_create_context_spec.rb |  6 ++++--
 spec/factories.rb                             |  1 -
 spec/features/security/group_access_spec.rb   | 12 +++++++-----
 spec/models/group_spec.rb                     |  6 +++---
 spec/models/project_spec.rb                   |  1 -
 spec/models/user_spec.rb                      | 10 ++++++----
 spec/requests/api/groups_spec.rb              | 18 ++++++++++++++----
 8 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb
index 71f29121179..99ec77a7613 100644
--- a/features/steps/group/group.rb
+++ b/features/steps/group/group.rb
@@ -10,7 +10,8 @@ class Groups < Spinach::FeatureSteps
   end
 
   And 'I have group with projects' do
-    @group   = create(:group, owner: current_user)
+    @group   = create(:group)
+    @group.add_owner(current_user)
     @project = create(:project, namespace: @group)
     @event   = create(:closed_issue_event, project: @project)
 
diff --git a/spec/contexts/projects_create_context_spec.rb b/spec/contexts/projects_create_context_spec.rb
index 7b5fa530a8a..8b2a49dbee5 100644
--- a/spec/contexts/projects_create_context_spec.rb
+++ b/spec/contexts/projects_create_context_spec.rb
@@ -25,13 +25,15 @@ describe Projects::CreateContext do
 
     context 'group namespace' do
       before do
-        @group = create :group, owner: @user
+        @group = create :group
+        @group.add_owner(@user)
+
         @opts.merge!(namespace_id: @group.id)
         @project = create_project(@user, @opts)
       end
 
       it { @project.should be_valid }
-      it { @project.owner.should == @user }
+      it { @project.owner.should == @group }
       it { @project.namespace.should == @group }
     end
 
diff --git a/spec/factories.rb b/spec/factories.rb
index 4c5e687ac3e..56561fe4595 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -71,7 +71,6 @@ FactoryGirl.define do
   factory :group do
     sequence(:name) { |n| "group#{n}" }
     path { name.downcase.gsub(/\s/, '_') }
-    owner
     type 'Group'
   end
 
diff --git a/spec/features/security/group_access_spec.rb b/spec/features/security/group_access_spec.rb
index b6167174f20..dea957962a8 100644
--- a/spec/features/security/group_access_spec.rb
+++ b/spec/features/security/group_access_spec.rb
@@ -10,11 +10,13 @@ describe "Group access" do
   describe "Group" do
     let(:group) { create(:group) }
 
+    let(:owner)   { create(:owner) }
     let(:master)   { create(:user) }
     let(:reporter) { create(:user) }
     let(:guest)    { create(:user) }
 
     before do
+      group.add_user(owner, Gitlab::Access::OWNER)
       group.add_user(master, Gitlab::Access::MASTER)
       group.add_user(reporter, Gitlab::Access::REPORTER)
       group.add_user(guest, Gitlab::Access::GUEST)
@@ -23,7 +25,7 @@ describe "Group access" do
     describe "GET /groups/:path" do
       subject { group_path(group) }
 
-      it { should be_allowed_for group.owner }
+      it { should be_allowed_for owner }
       it { should be_allowed_for master }
       it { should be_allowed_for reporter }
       it { should be_allowed_for :admin }
@@ -35,7 +37,7 @@ describe "Group access" do
     describe "GET /groups/:path/issues" do
       subject { issues_group_path(group) }
 
-      it { should be_allowed_for group.owner }
+      it { should be_allowed_for owner }
       it { should be_allowed_for master }
       it { should be_allowed_for reporter }
       it { should be_allowed_for :admin }
@@ -47,7 +49,7 @@ describe "Group access" do
     describe "GET /groups/:path/merge_requests" do
       subject { merge_requests_group_path(group) }
 
-      it { should be_allowed_for group.owner }
+      it { should be_allowed_for owner }
       it { should be_allowed_for master }
       it { should be_allowed_for reporter }
       it { should be_allowed_for :admin }
@@ -59,7 +61,7 @@ describe "Group access" do
     describe "GET /groups/:path/members" do
       subject { members_group_path(group) }
 
-      it { should be_allowed_for group.owner }
+      it { should be_allowed_for owner }
       it { should be_allowed_for master }
       it { should be_allowed_for reporter }
       it { should be_allowed_for :admin }
@@ -71,7 +73,7 @@ describe "Group access" do
     describe "GET /groups/:path/edit" do
       subject { edit_group_path(group) }
 
-      it { should be_allowed_for group.owner }
+      it { should be_allowed_for owner }
       it { should be_denied_for master }
       it { should be_denied_for reporter }
       it { should be_allowed_for :admin }
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 78c39548eb4..ce1aa05bcd7 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -26,10 +26,10 @@ describe Group do
   it { should validate_uniqueness_of(:name) }
   it { should validate_presence_of :path }
   it { should validate_uniqueness_of(:path) }
-  it { should validate_presence_of :owner }
+  it { should_not validate_presence_of :owner }
 
   describe :users do
-    it { group.users.should == [group.owner] }
+    it { group.users.should == group.owners }
   end
 
   describe :human_name do
@@ -38,7 +38,7 @@ describe Group do
 
   describe :add_users do
     let(:user) { create(:user) }
-    before { group.add_users([user.id], UsersGroup::MASTER) }
+    before { group.add_user(user, UsersGroup::MASTER) }
 
     it { group.users_groups.masters.map(&:user).should include(user) }
   end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index c3d2bf5d4a6..47ae760a7ed 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -85,7 +85,6 @@ describe Project do
     it { should respond_to(:execute_hooks) }
     it { should respond_to(:transfer) }
     it { should respond_to(:name_with_namespace) }
-    it { should respond_to(:namespace_owner) }
     it { should respond_to(:owner) }
     it { should respond_to(:path_with_namespace) }
   end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index c879900f8fd..f6c9f82c4ee 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -130,11 +130,12 @@ describe User do
     before do
       ActiveRecord::Base.observers.enable(:user_observer)
       @user = create :user
-      @group = create :group, owner: @user
+      @group = create :group
+      @group.add_owner(@user)
     end
 
     it { @user.several_namespaces?.should be_true }
-    it { @user.namespaces.should include(@user.namespace, @group) }
+    it { @user.namespaces.should include(@user.namespace) }
     it { @user.authorized_groups.should == [@group] }
     it { @user.owned_groups.should == [@group] }
   end
@@ -144,9 +145,10 @@ describe User do
       ActiveRecord::Base.observers.enable(:user_observer)
       @user = create :user
       @user2 = create :user
-      @group = create :group, owner: @user
+      @group = create :group
+      @group.add_owner(@user)
 
-      @group.add_users([@user2.id], UsersGroup::OWNER)
+      @group.add_user(@user2, UsersGroup::OWNER)
     end
 
     it { @user2.several_namespaces?.should be_true }
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index f7fd27523b0..a6ce72e11e9 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -6,8 +6,13 @@ describe API::API do
   let(:user1) { create(:user) }
   let(:user2) { create(:user) }
   let(:admin) { create(:admin) }
-  let!(:group1) { create(:group, owner: user1) }
-  let!(:group2) { create(:group, owner: user2) }
+  let!(:group1) { create(:group) }
+  let!(:group2) { create(:group) }
+
+  before do
+    group1.add_owner(user1)
+    group2.add_owner(user2)
+  end
 
   describe "GET /groups" do
     context "when unauthenticated" do
@@ -130,14 +135,19 @@ describe API::API do
     let(:master) { create(:user) }
     let(:guest) { create(:user) }
     let!(:group_with_members) do
-      group = create(:group, owner: owner)
+      group = create(:group)
       group.add_users([reporter.id], UsersGroup::REPORTER)
       group.add_users([developer.id], UsersGroup::DEVELOPER)
       group.add_users([master.id], UsersGroup::MASTER)
       group.add_users([guest.id], UsersGroup::GUEST)
       group
     end
-    let!(:group_no_members) { create(:group, owner: owner) }
+    let!(:group_no_members) { create(:group) }
+
+    before do
+      group_with_members.add_owner owner
+      group_no_members.add_owner owner
+    end
 
     describe "GET /groups/:id/members" do
       context "when authenticated as user that is part or the group" do
-- 
GitLab


From fe0e5b003203ee64605850bc9dfa44e5465a9278 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 26 Sep 2013 15:06:00 +0300
Subject: [PATCH 167/248] Mention group permissions on Help#permissions page

---
 app/views/help/permissions.html.haml | 50 ++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/app/views/help/permissions.html.haml b/app/views/help/permissions.html.haml
index da5210bad3d..bab1e7c0a41 100644
--- a/app/views/help/permissions.html.haml
+++ b/app/views/help/permissions.html.haml
@@ -1,6 +1,9 @@
 = render layout: 'help/layout' do
   %h3.page-title Permissions
+  %p.light User has different abilities depends on access level he has in particular group or project
+  %hr
 
+  %h4 Project:
   %table.table
     %thead
       %tr
@@ -158,3 +161,50 @@
         %td
         %td
         %td.permission-x &#10003;
+
+  %h4 Group
+  %table.table
+    %thead
+      %tr
+        %th Action
+        %th Guest
+        %th Reporter
+        %th Developer
+        %th Master
+        %th Owner
+    %tbody
+      %tr
+        %td Browse group
+        %td.permission-x &#10003;
+        %td.permission-x &#10003;
+        %td.permission-x &#10003;
+        %td.permission-x &#10003;
+        %td.permission-x &#10003;
+      %tr
+        %td Edit group
+        %td
+        %td
+        %td
+        %td
+        %td.permission-x &#10003;
+      %tr
+        %td Create project in group
+        %td
+        %td
+        %td
+        %td
+        %td.permission-x &#10003;
+      %tr
+        %td Manage group members
+        %td
+        %td
+        %td
+        %td
+        %td.permission-x &#10003;
+      %tr
+        %td Remove group
+        %td
+        %td
+        %td
+        %td
+        %td.permission-x &#10003;
-- 
GitLab


From 24358389ea404c5dc5b7f6d497f7d2c288cb58fe Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 26 Sep 2013 15:08:33 +0300
Subject: [PATCH 168/248] Mention permissions table on Group#members page

---
 app/views/groups/members.html.haml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/app/views/groups/members.html.haml b/app/views/groups/members.html.haml
index 77bab11b331..124560e4786 100644
--- a/app/views/groups/members.html.haml
+++ b/app/views/groups/members.html.haml
@@ -2,6 +2,9 @@
   Group members
 %p.light
   Members of group have access to all group projects.
+  Read more about permissions
+  %strong= link_to "here", help_permissions_path, class: "vlink"
+
 %hr
 - can_manage_group =  current_user.can? :manage_group, @group
 .ui-box
-- 
GitLab


From 81f87609b797937eb84d906b94f234742461ab05 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 26 Sep 2013 15:56:05 +0300
Subject: [PATCH 169/248] Remove issues search rspec since we test it with
 spinach too

---
 features/project/issues/issues.feature |  1 -
 spec/features/issues_spec.rb           | 34 --------------------------
 2 files changed, 35 deletions(-)

diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature
index 022188f8250..a4415736df7 100644
--- a/features/project/issues/issues.feature
+++ b/features/project/issues/issues.feature
@@ -47,7 +47,6 @@ Feature: Project Issues
     Then I should not see "Release 0.4" in issues
     And I should not see "Release 0.3" in issues
 
-
   @javascript
   Scenario: I search all issues
     Given I click link "All"
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
index 6fff59f036f..0c09279e3dc 100644
--- a/spec/features/issues_spec.rb
+++ b/spec/features/issues_spec.rb
@@ -45,40 +45,6 @@ describe "Issues" do
     end
   end
 
-  describe "Search issue", js: true do
-    before do
-      ['foobar', 'foobar2', 'gitlab'].each do |title|
-        create(:issue,
-               author: @user,
-               assignee: @user,
-               project: project,
-               title: title)
-      end
-    end
-
-    it "should be able to search on different statuses" do
-      issue = Issue.first # with title 'foobar'
-      issue.close
-
-      visit project_issues_path(project)
-      click_link 'Closed'
-      fill_in 'issue_search', with: 'foobar'
-
-      page.should have_content 'foobar'
-      page.should_not have_content 'foobar2'
-      page.should_not have_content 'gitlab'
-    end
-
-    it "should search for term and return the correct results" do
-      visit project_issues_path(project)
-      fill_in 'issue_search', with: 'foobar'
-
-      page.should have_content 'foobar'
-      page.should have_content 'foobar2'
-      page.should_not have_content 'gitlab'
-    end
-  end
-
   describe "Filter issue" do
     before do
       ['foobar', 'barbaz', 'gitlab'].each do |title|
-- 
GitLab


From 79a2757d04a9b85de111762a7589d3000ad05297 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 26 Sep 2013 16:00:11 +0300
Subject: [PATCH 170/248] Add sleep in tests to prevent random failing when
 next test starts before ajax requests for old one in progress

---
 features/steps/project/project_issues.rb | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/features/steps/project/project_issues.rb b/features/steps/project/project_issues.rb
index 6c18177498f..70e5cdf4a94 100644
--- a/features/steps/project/project_issues.rb
+++ b/features/steps/project/project_issues.rb
@@ -58,14 +58,17 @@ class ProjectIssues < Spinach::FeatureSteps
 
   Given 'I fill in issue search with "Release"' do
     fill_in 'issue_search', with: "Release"
+    sleep 0.05
   end
 
   Given 'I fill in issue search with "Bug"' do
     fill_in 'issue_search', with: "Bug"
+    sleep 0.05
   end
 
   And 'I fill in issue search with "0.3"' do
     fill_in 'issue_search', with: "0.3"
+    sleep 0.05
   end
 
   And 'I fill in issue search with "Something"' do
-- 
GitLab


From b5f3ac5eb3871c1ccd364947d67b36eacd0dc931 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 26 Sep 2013 19:05:55 +0300
Subject: [PATCH 171/248] Fix issues search test

---
 features/project/issues/issues.feature   |  2 ++
 features/steps/project/project_issues.rb | 12 ++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature
index a4415736df7..5db9e01068c 100644
--- a/features/project/issues/issues.feature
+++ b/features/project/issues/issues.feature
@@ -3,6 +3,7 @@ Feature: Project Issues
     Given I sign in as a user
     And I own project "Shop"
     And project "Shop" have "Release 0.4" open issue
+    And project "Shop" have "Tweet feature" open issue
     And project "Shop" have "Release 0.3" closed issue
     And I visit project "Shop" issues page
 
@@ -40,6 +41,7 @@ Feature: Project Issues
     Given I fill in issue search with "Release"
     Then I should see "Release 0.4" in issues
     And I should not see "Release 0.3" in issues
+    And I should not see "Tweet feature" in issues
 
   @javascript
   Scenario: I search issue that not exist
diff --git a/features/steps/project/project_issues.rb b/features/steps/project/project_issues.rb
index 70e5cdf4a94..70c9b3a3f2e 100644
--- a/features/steps/project/project_issues.rb
+++ b/features/steps/project/project_issues.rb
@@ -12,6 +12,10 @@ class ProjectIssues < Spinach::FeatureSteps
     page.should_not have_content "Release 0.3"
   end
 
+  And 'I should not see "Tweet feature" in issues' do
+    page.should_not have_content "Tweet feature"
+  end
+
   Given 'I click link "Closed"' do
     click_link "Closed"
   end
@@ -123,6 +127,14 @@ class ProjectIssues < Spinach::FeatureSteps
            author: project.users.first)
   end
 
+  And 'project "Shop" have "Tweet feature" open issue' do
+    project = Project.find_by_name("Shop")
+    create(:issue,
+           title: "Tweet feature",
+           project: project,
+           author: project.users.first)
+  end
+
   And 'project "Shop" have "Release 0.3" closed issue' do
     project = Project.find_by_name("Shop")
     create(:closed_issue,
-- 
GitLab


From 14bc03cafb478d215e1856d45e4684cc0cc5a84e Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 26 Sep 2013 19:22:04 +0300
Subject: [PATCH 172/248] Dont test 1.9 with travis

---
 .travis.yml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index d7fbbc7bbcb..3ed3dec1425 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,7 +8,6 @@ branches:
   only:
     - 'master'
 rvm:
-  - 1.9.3-p392
   - 2.0.0
 services:
   - mysql
-- 
GitLab


From 2dc35e4a5035cc2abd6ae22d72a4b5f2c415ac8c Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 26 Sep 2013 19:46:31 +0300
Subject: [PATCH 173/248] Explain on dashboard that limit amount of projects
 displayed

---
 app/controllers/dashboard_controller.rb |  6 +++++-
 app/views/dashboard/_project.html.haml  | 12 ++++++++++++
 app/views/dashboard/_projects.html.haml | 23 +++++++++--------------
 3 files changed, 26 insertions(+), 15 deletions(-)
 create mode 100644 app/views/dashboard/_project.html.haml

diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 33b2a5cd7e7..ac319384434 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -5,10 +5,14 @@ class DashboardController < ApplicationController
   before_filter :event_filter, only: :show
 
   def show
+    # Fetch only 30 projects.
+    # If user needs more - point to Dashboard#projects page
+    @projects_limit = 30
+
     @groups = current_user.authorized_groups.sort_by(&:human_name)
     @has_authorized_projects = @projects.count > 0
     @projects_count = @projects.count
-    @projects = @projects.limit(20)
+    @projects = @projects.limit(@projects_limit)
 
     @events = Event.in_projects(current_user.authorized_projects.pluck(:id))
     @events = @event_filter.apply_filter(@events)
diff --git a/app/views/dashboard/_project.html.haml b/app/views/dashboard/_project.html.haml
new file mode 100644
index 00000000000..50b833f3d82
--- /dev/null
+++ b/app/views/dashboard/_project.html.haml
@@ -0,0 +1,12 @@
+= link_to project_path(project), class: dom_class(project) do
+  %span.namespace-name
+    - if project.namespace
+      = project.namespace.human_name
+      \/
+  %span.project-name.filter-title
+    = truncate(project.name, length: 25)
+  %span.arrow
+    %i.icon-angle-right
+  %span.last-activity
+    %span Last activity:
+    %span.date= project_last_activity(project)
diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml
index 90b843de016..b79b27fc95a 100644
--- a/app/views/dashboard/_projects.html.haml
+++ b/app/views/dashboard/_projects.html.haml
@@ -10,21 +10,16 @@
   %ul.well-list.dash-list
     - projects.each do |project|
       %li.project-row
-        = link_to project_path(project), class: dom_class(project) do
-          %span.namespace-name
-            - if project.namespace
-              = project.namespace.human_name
-              \/
-          %span.project-name.filter-title
-            = truncate(project.name, length: 25)
-          %span.arrow
-            %i.icon-angle-right
-          %span.last-activity
-            %span Last activity:
-            %span.date= project_last_activity(project)
+        = render "project", project: project
+
     - if projects.blank?
       %li
         %h3.nothing_here_message There are no projects here.
-    - if @projects_count > 20
+    - if @projects_count > @projects_limit
       %li.bottom
-        %strong= link_to "show all projects", projects_dashboard_path
+        %span.light
+          #{@projects_limit} of #{pluralize(@projects_count, 'project')} displayed.
+        .pull-right.append-right-10
+          = link_to projects_dashboard_path do
+            Show all
+            %i.icon-angle-right
-- 
GitLab


From 7b91e02d4f73803f075b1073d12332c93bfb5bf6 Mon Sep 17 00:00:00 2001
From: Zane Shannon <z@zcs.me>
Date: Thu, 26 Sep 2013 13:01:22 -0500
Subject: [PATCH 174/248] Fixed grammatical mistake in init.d status output.

"its" not "it's".
---
 lib/support/init.d/gitlab | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
index dbdf7db114b..0248284f8d5 100755
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -204,7 +204,7 @@ status() {
       printf "The GitLab Sidekiq job dispatcher is \033[31mnot running\033[0m.\n"
   fi
   if [ "$web_status" = "0" -a "$sidekiq_status" = "0" ]; then
-    printf "GitLab and all it's components are \033[32mup and running\033[0m.\n"
+    printf "GitLab and all its components are \033[32mup and running\033[0m.\n"
   fi
 }
 
-- 
GitLab


From 9921c6dafad72f1b77e4239722008254a2da5848 Mon Sep 17 00:00:00 2001
From: Perry Faro <perryfaro@live.nl>
Date: Fri, 27 Sep 2013 11:56:30 +0200
Subject: [PATCH 175/248]  Add check if the signup setting is enabled. fixes
 #4832

---
 app/views/devise/shared/_links.erb | 2 +-
 config/gitlab.yml.example          | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/app/views/devise/shared/_links.erb b/app/views/devise/shared/_links.erb
index a47b5ff1ec7..db931b86288 100644
--- a/app/views/devise/shared/_links.erb
+++ b/app/views/devise/shared/_links.erb
@@ -2,7 +2,7 @@
   <%= link_to "Sign in", new_session_path(resource_name), class: "btn" %><br />
 <% end -%>
 
-<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
+<%- if devise_mapping.registerable? && controller_name != 'registrations' && Gitlab.config.gitlab.signup_enabled %>
   <%= link_to "Sign up", new_registration_path(resource_name) %><br />
 <% end -%>
 
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 073e76307a0..ee29d52815c 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -52,7 +52,8 @@ production: &base
 
 
     ## Users management
-    # signup_enabled: true          # default: false - Account passwords are not sent via the email if signup is enabled.
+    # default: false - Account passwords are not sent via the email if signup is enabled. 
+    # signup_enabled: true
 
     ## Automatic issue closing
     # If a commit message matches this regular express, all issues referenced from the matched text will be closed
-- 
GitLab


From c59b7fd80b16e6b18836ff7f09a0ede60c47ed1f Mon Sep 17 00:00:00 2001
From: Jacob Vosmaer <contact@jacobvosmaer.nl>
Date: Fri, 27 Sep 2013 12:57:05 +0200
Subject: [PATCH 176/248] Check whether only one sidekiq is running

---
 lib/tasks/gitlab/check.rake | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index c445c0fbddd..59af211f49f 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -608,6 +608,7 @@ namespace :gitlab do
       start_checking "Sidekiq"
 
       check_sidekiq_running
+      only_one_sidekiq_running
 
       finished_checking "Sidekiq"
     end
@@ -619,7 +620,7 @@ namespace :gitlab do
     def check_sidekiq_running
       print "Running? ... "
 
-      if run_and_match("ps aux | grep -i sidekiq", /sidekiq \d+\.\d+\.\d+.+$/)
+      if sidekiq_process_match
         puts "yes".green
       else
         puts "no".red
@@ -633,6 +634,30 @@ namespace :gitlab do
         fix_and_rerun
       end
     end
+
+    def only_one_sidekiq_running
+      sidekiq_match = sidekiq_process_match
+      return unless sidekiq_match
+
+      print 'Number of Sidekiq processes ... '
+      if sidekiq_match.length == 1
+        puts '1'.green
+      else
+        puts "#{sidekiq_match.length}".red
+        try_fixing_it(
+          'Unless you are running another Rails application on this server there should only be one Sidekiq process.',
+          'sudo service gitlab stop',
+          'sudo pkill -f sidekiq',
+          'sleep 10 && sudo pkill -9 -f sidekiq',
+          'sudo service gitlab start'
+        )
+        fix_and_rerun
+      end
+    end
+
+    def sidekiq_process_match
+      run_and_match("ps aux | grep -i sidekiq", /(sidekiq \d+\.\d+\.\d+.+$)/)
+    end
   end
 
 
-- 
GitLab


From 69437092880de8b08d915d9f2e7066c702b7b0ec Mon Sep 17 00:00:00 2001
From: Thomas Misilo <misilot@fit.edu>
Date: Fri, 27 Sep 2013 08:39:38 -0400
Subject: [PATCH 177/248] Added reference to the line
 "ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"" , as it talked about in the
 gitlab.yml.example

---
 config/unicorn.rb.example | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example
index 5c933df073a..502727fdfe4 100644
--- a/config/unicorn.rb.example
+++ b/config/unicorn.rb.example
@@ -8,6 +8,9 @@
 # See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
 # documentation.
 
+# Uncomment and customize the next line to run in a non-root path
+# ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
+
 # Use at least one worker per core if you're on a dedicated server,
 # more will usually help for _short_ waits on databases/caches.
 worker_processes 2
-- 
GitLab


From 685b6fd57e31ea0c4782a1df9eb90e3a404b57b6 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 27 Sep 2013 16:25:24 +0300
Subject: [PATCH 178/248] rewrite issues search test to prevent ajax requests
 running after test

---
 features/project/issues/issues.feature   | 10 +++++-----
 features/steps/project/project_issues.rb | 23 ++++++++++-------------
 2 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature
index 5db9e01068c..67986784bc7 100644
--- a/features/project/issues/issues.feature
+++ b/features/project/issues/issues.feature
@@ -3,7 +3,7 @@ Feature: Project Issues
     Given I sign in as a user
     And I own project "Shop"
     And project "Shop" have "Release 0.4" open issue
-    And project "Shop" have "Tweet feature" open issue
+    And project "Shop" have "Tweet control" open issue
     And project "Shop" have "Release 0.3" closed issue
     And I visit project "Shop" issues page
 
@@ -38,20 +38,20 @@ Feature: Project Issues
 
   @javascript
   Scenario: I search issue
-    Given I fill in issue search with "Release"
+    Given I fill in issue search with "Re"
     Then I should see "Release 0.4" in issues
     And I should not see "Release 0.3" in issues
-    And I should not see "Tweet feature" in issues
+    And I should not see "Tweet control" in issues
 
   @javascript
   Scenario: I search issue that not exist
-    Given I fill in issue search with "Bug"
+    Given I fill in issue search with "Bu"
     Then I should not see "Release 0.4" in issues
     And I should not see "Release 0.3" in issues
 
   @javascript
   Scenario: I search all issues
     Given I click link "All"
-    And I fill in issue search with "0.3"
+    And I fill in issue search with ".3"
     Then I should see "Release 0.3" in issues
     And I should not see "Release 0.4" in issues
diff --git a/features/steps/project/project_issues.rb b/features/steps/project/project_issues.rb
index 70c9b3a3f2e..801fff78a52 100644
--- a/features/steps/project/project_issues.rb
+++ b/features/steps/project/project_issues.rb
@@ -12,8 +12,8 @@ class ProjectIssues < Spinach::FeatureSteps
     page.should_not have_content "Release 0.3"
   end
 
-  And 'I should not see "Tweet feature" in issues' do
-    page.should_not have_content "Tweet feature"
+  And 'I should not see "Tweet control" in issues' do
+    page.should_not have_content "Tweet control"
   end
 
   Given 'I click link "Closed"' do
@@ -60,19 +60,16 @@ class ProjectIssues < Spinach::FeatureSteps
     page.should have_content issue.project.name
   end
 
-  Given 'I fill in issue search with "Release"' do
-    fill_in 'issue_search', with: "Release"
-    sleep 0.05
+  Given 'I fill in issue search with "Re"' do
+    fill_in 'issue_search', with: "Re"
   end
 
-  Given 'I fill in issue search with "Bug"' do
-    fill_in 'issue_search', with: "Bug"
-    sleep 0.05
+  Given 'I fill in issue search with "Bu"' do
+    fill_in 'issue_search', with: "Bu"
   end
 
-  And 'I fill in issue search with "0.3"' do
-    fill_in 'issue_search', with: "0.3"
-    sleep 0.05
+  And 'I fill in issue search with ".3"' do
+    fill_in 'issue_search', with: ".3"
   end
 
   And 'I fill in issue search with "Something"' do
@@ -127,10 +124,10 @@ class ProjectIssues < Spinach::FeatureSteps
            author: project.users.first)
   end
 
-  And 'project "Shop" have "Tweet feature" open issue' do
+  And 'project "Shop" have "Tweet control" open issue' do
     project = Project.find_by_name("Shop")
     create(:issue,
-           title: "Tweet feature",
+           title: "Tweet control",
            project: project,
            author: project.users.first)
   end
-- 
GitLab


From bf309fcfbea4de894bcc317487efea47203668ac Mon Sep 17 00:00:00 2001
From: Johannes Schleifenbaum <johannes@js-webcoding.de>
Date: Thu, 26 Sep 2013 15:40:44 +0200
Subject: [PATCH 179/248] [gitlab:check] Fix detecting the status of sidekiq

If you are running another sidekiq instance on your server, e.g. GitLab
CI, the check script would parse the output of `ps aux` searching for
`sidekiq` and returning success, although the GitLab sidekiq may not be
running.

Now the `ps` call will only print the processes run by the GitLab user.
---
 lib/tasks/gitlab/check.rake | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 59af211f49f..4ae0e1fc5f9 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -645,7 +645,6 @@ namespace :gitlab do
       else
         puts "#{sidekiq_match.length}".red
         try_fixing_it(
-          'Unless you are running another Rails application on this server there should only be one Sidekiq process.',
           'sudo service gitlab stop',
           'sudo pkill -f sidekiq',
           'sleep 10 && sudo pkill -9 -f sidekiq',
@@ -656,7 +655,7 @@ namespace :gitlab do
     end
 
     def sidekiq_process_match
-      run_and_match("ps aux | grep -i sidekiq", /(sidekiq \d+\.\d+\.\d+.+$)/)
+      run_and_match("ps ux | grep -i sidekiq", /(sidekiq \d+\.\d+\.\d+.+$)/)
     end
   end
 
-- 
GitLab


From 6f8d9a436cef78f266eee799f465dd1c5581a3a1 Mon Sep 17 00:00:00 2001
From: Denix <denics@free.fr>
Date: Sun, 25 Aug 2013 23:37:42 +0200
Subject: [PATCH 180/248] Update databases.md

run mysql_secure_installation to secure the freshly installed mysql server
---
 doc/install/databases.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/doc/install/databases.md b/doc/install/databases.md
index 5ec1d0c6524..6477e1c967c 100644
--- a/doc/install/databases.md
+++ b/doc/install/databases.md
@@ -14,6 +14,9 @@ GitLab supports the following databases:
     # Pick a database root password (can be anything), type it and press enter
     # Retype the database root password and press enter
 
+    # Secure your installation.
+    sudo mysql_secure_installation
+    
     # Login to MySQL
     mysql -u root -p
 
-- 
GitLab


From ff0e3097ae2717de2498bd484d3ef11abc630946 Mon Sep 17 00:00:00 2001
From: Thomas Misilo <misilot@fit.edu>
Date: Sat, 28 Sep 2013 07:40:48 -0400
Subject: [PATCH 181/248] Updated at the request of @f0k

---
 config/unicorn.rb.example | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example
index 502727fdfe4..e4e13426831 100644
--- a/config/unicorn.rb.example
+++ b/config/unicorn.rb.example
@@ -8,7 +8,13 @@
 # See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
 # documentation.
 
-# Uncomment and customize the next line to run in a non-root path
+# Uncomment and customize the last line to run in a non-root path
+# WARNING: This feature is known to work, but unsupported
+# Note that three settings need to be changed for this to work.
+# 1) In your application.rb file: config.relative_url_root = "/gitlab"
+# 2) In your gitlab.yml file: relative_url_root: /gitlab
+# 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
+#
 # ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
 
 # Use at least one worker per core if you're on a dedicated server,
-- 
GitLab


From eddb8af0164ffae1b65d000b67469c202f4bce77 Mon Sep 17 00:00:00 2001
From: Boyan Tabakov <boyan.tabakov@futurice.com>
Date: Wed, 31 Jul 2013 13:52:23 +0300
Subject: [PATCH 182/248] Extended User API to expose admin and
 can_create_group for user creation/updating.

Also, is_admin and can_create_group are exposed in the user information.
Fixed attributes_for_keys to process properly keys with boolean values (since false.present? is false).
---
 doc/api/users.md                | 39 ++++++++++++++++++++-------------
 lib/api/entities.rb             |  7 +++---
 lib/api/helpers.rb              |  2 +-
 lib/api/users.rb                | 14 +++++++++---
 spec/requests/api/users_spec.rb | 28 ++++++++++++++++++++++-
 5 files changed, 66 insertions(+), 24 deletions(-)

diff --git a/doc/api/users.md b/doc/api/users.md
index 49afbab8c6a..50c0f560d87 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -23,7 +23,9 @@ GET /users
     "extern_uid": "john.smith",
     "provider": "provider_name",
     "theme_id": 1,
-    "color_scheme_id": 2
+    "color_scheme_id": 2,
+    "is_admin": false,
+    "can_create_group": true
   },
   {
     "id": 2,
@@ -39,7 +41,9 @@ GET /users
     "extern_uid": "jack.smith",
     "provider": "provider_name",
     "theme_id": 1,
-    "color_scheme_id": 3
+    "color_scheme_id": 3,
+    "is_admin": false,
+    "can_create_group": true
   }
 ]
 ```
@@ -72,7 +76,9 @@ Parameters:
   "extern_uid": "john.smith",
   "provider": "provider_name",
   "theme_id": 1,
-  "color_scheme_id": 2
+  "color_scheme_id": 2,
+  "is_admin": false,
+  "can_create_group": true
 }
 ```
 
@@ -87,17 +93,19 @@ POST /users
 
 Parameters:
 
-+ `email` (required)          - Email
-+ `password` (required)       - Password
-+ `username` (required)       - Username
-+ `name` (required)           - Name
-+ `skype` (optional)          - Skype ID
-+ `linkedin` (optional)       - Linkedin
-+ `twitter` (optional)        - Twitter account
-+ `projects_limit` (optional) - Number of projects user can create
-+ `extern_uid` (optional)     - External UID
-+ `provider` (optional)       - External provider name
-+ `bio` (optional)            - User's bio
++ `email` (required)            - Email
++ `password` (required)         - Password
++ `username` (required)         - Username
++ `name` (required)             - Name
++ `skype` (optional)            - Skype ID
++ `linkedin` (optional)         - Linkedin
++ `twitter` (optional)          - Twitter account
++ `projects_limit` (optional)   - Number of projects user can create
++ `extern_uid` (optional)       - External UID
++ `provider` (optional)         - External provider name
++ `bio` (optional)              - User's bio
++ `admin` (optional)            - User is admin - true or false (default)
++ `can_create_group` (optional) - User can create groups - true or false
 
 
 ## User modification
@@ -121,6 +129,8 @@ Parameters:
 + `extern_uid`                        - External UID
 + `provider`                          - External provider name
 + `bio`                               - User's bio
++ `admin` (optional)                  - User is admin - true or false (default)
++ `can_create_group` (optional)       - User can create groups - true or false
 
 Note, at the moment this method does only return a 404 error, even in cases where a 409 (Conflict) would
 be more appropriate, e.g. when renaming the email address to some existing one.
@@ -166,7 +176,6 @@ GET /user
   "color_scheme_id": 2,
   "is_admin": false,
   "can_create_group" : true,
-  "can_create_team" : true,
   "can_create_project" : true
 }
 ```
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 1f35e9ec5fc..ab949f530ab 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -3,6 +3,9 @@ module API
     class User < Grape::Entity
       expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter,
              :theme_id, :color_scheme_id, :state, :created_at, :extern_uid, :provider
+      expose :is_admin?, as: :is_admin
+      expose :can_create_group?, as: :can_create_group
+      expose :can_create_project?, as: :can_create_project
     end
 
     class UserSafe < Grape::Entity
@@ -15,10 +18,6 @@ module API
 
     class UserLogin < User
       expose :private_token
-      expose :is_admin?, as: :is_admin
-      expose :can_create_group?, as: :can_create_group
-      expose :can_create_project?, as: :can_create_project
-      expose :can_create_team?, as: :can_create_team
     end
 
     class Hook < Grape::Entity
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 4f189f35196..860848b2995 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -82,7 +82,7 @@ module API
     def attributes_for_keys(keys)
       attrs = {}
       keys.each do |key|
-        attrs[key] = params[key] if params[key].present?
+        attrs[key] = params[key] if params[key].present? or (params.has_key?(key) and params[key] == false)
       end
       attrs
     end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 00dc2311ffd..54d3aeecb70 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -40,13 +40,17 @@ module API
       #   extern_uid                        - External authentication provider UID
       #   provider                          - External provider
       #   bio                               - Bio
+      #   admin                             - User is admin - true or false (default)
+      #   can_create_group                  - User can create groups - true or false
       # Example Request:
       #   POST /users
       post do
         authenticated_as_admin!
         required_attributes! [:email, :password, :name, :username]
-        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
+        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin]
         user = User.build_user(attrs, as: :admin)
+        admin = attrs.delete(:admin)
+        user.admin = admin unless admin.nil?
         if user.save
           present user, with: Entities::User
         else
@@ -67,16 +71,20 @@ module API
       #   extern_uid                        - External authentication provider UID
       #   provider                          - External provider
       #   bio                               - Bio
+      #   admin                             - User is admin - true or false (default)
+      #   can_create_group                  - User can create groups - true or false
       # Example Request:
       #   PUT /users/:id
       put ":id" do
         authenticated_as_admin!
 
-        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
+        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin]
         user = User.find(params[:id])
         not_found!("User not found") unless user
 
-        if user.update_attributes(attrs)
+        admin = attrs.delete(:admin)
+        user.admin = admin unless admin.nil?
+        if user.update_attributes(attrs, as: :admin)
           present user, with: Entities::User
         else
           not_found!
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 2fced3ec945..4a299d3d958 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -52,6 +52,16 @@ describe API::API do
       }.to change { User.count }.by(1)
     end
 
+    it "should create user with correct attributes" do
+      post api('/users', admin), attributes_for(:user, admin: true, can_create_group: true)
+      response.status.should == 201
+      user_id = json_response['id']
+      new_user = User.find(user_id)
+      new_user.should_not == nil
+      new_user.admin.should == true
+      new_user.can_create_group.should == true
+    end
+
     it "should return 201 Created on success" do
       post api("/users", admin), attributes_for(:user, projects_limit: 3)
       response.status.should == 201
@@ -135,6 +145,8 @@ describe API::API do
   end
 
   describe "PUT /users/:id" do
+    let!(:admin_user) { create(:admin) }
+
     before { admin }
 
     it "should update user with new bio" do
@@ -144,6 +156,21 @@ describe API::API do
       user.reload.bio.should == 'new test bio'
     end
 
+    it "should update admin status" do
+      put api("/users/#{user.id}", admin), {admin: true}
+      response.status.should == 200
+      json_response['is_admin'].should == true
+      user.reload.admin.should == true
+    end
+
+    it "should not update admin status" do
+      put api("/users/#{admin_user.id}", admin), {can_create_group: false}
+      response.status.should == 200
+      json_response['is_admin'].should == true
+      admin_user.reload.admin.should == true
+      admin_user.can_create_group.should == false
+    end
+
     it "should not allow invalid update" do
       put api("/users/#{user.id}", admin), {email: 'invalid email'}
       response.status.should == 404
@@ -228,7 +255,6 @@ describe API::API do
       response.status.should == 200
       json_response['email'].should == user.email
       json_response['is_admin'].should == user.is_admin?
-      json_response['can_create_team'].should == user.can_create_team?
       json_response['can_create_project'].should == user.can_create_project?
       json_response['can_create_group'].should == user.can_create_group?
     end
-- 
GitLab


From f17ba573235306603fb0716063b040e5f8634dfa Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 29 Sep 2013 15:44:49 +0300
Subject: [PATCH 183/248] Update some development dependencies

---
 Gemfile.lock | 35 ++++++++++++++++++++---------------
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/Gemfile.lock b/Gemfile.lock
index d6739cb87ac..59d67d4efe9 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -41,15 +41,15 @@ GEM
     addressable (2.3.4)
     arel (3.0.2)
     asciidoctor (0.1.3)
-    awesome_print (1.1.0)
+    awesome_print (1.2.0)
     backports (3.3.2)
     bcrypt-ruby (3.1.1)
-    better_errors (0.9.0)
+    better_errors (1.0.1)
       coderay (>= 1.0.0)
       erubis (>= 2.6.6)
     binding_of_caller (0.7.2)
       debug_inspector (>= 0.0.1)
-    bootstrap-sass (2.3.2.0)
+    bootstrap-sass (2.3.2.2)
       sass (~> 3.2)
     builder (3.0.4)
     capybara (2.1.0)
@@ -73,7 +73,7 @@ GEM
       sass-rails (>= 3.2)
     chunky_png (1.2.8)
     cliver (0.2.1)
-    code_analyzer (0.3.2)
+    code_analyzer (0.4.3)
       sexp_processor
     coderay (1.0.9)
     coffee-rails (3.2.2)
@@ -92,11 +92,11 @@ GEM
     compass-rails (1.0.3)
       compass (>= 0.12.2, < 0.14)
     connection_pool (1.1.0)
-    coveralls (0.6.7)
-      colorize
+    coveralls (0.7.0)
       multi_json (~> 1.3)
       rest-client
       simplecov (>= 0.7)
+      term-ansicolor
       thor
     crack (0.4.0)
       safe_yaml (~> 0.9.0)
@@ -133,7 +133,7 @@ GEM
       multipart-post (~> 1.1)
     faraday_middleware (0.9.0)
       faraday (>= 0.7.4, < 0.9)
-    ffaker (1.16.1)
+    ffaker (1.18.0)
     ffi (1.9.0)
     fog (1.3.1)
       builder
@@ -145,7 +145,7 @@ GEM
       net-ssh (>= 2.1.3)
       nokogiri (~> 1.5.0)
       ruby-hmac
-    font-awesome-rails (3.2.1.2)
+    font-awesome-rails (3.2.1.3)
       railties (>= 3.2, < 5.0)
     foreman (0.63.0)
       dotenv (>= 0.7)
@@ -278,7 +278,7 @@ GEM
     minitest (4.7.4)
     modernizr (2.6.2)
       sprockets (~> 2.0)
-    multi_json (1.7.9)
+    multi_json (1.8.0)
     multi_xml (0.5.4)
     multipart-post (1.2.0)
     mysql2 (0.3.11)
@@ -338,7 +338,7 @@ GEM
       rack
     rack-cache (1.2)
       rack (>= 0.4)
-    rack-mini-profiler (0.1.26)
+    rack-mini-profiler (0.1.31)
       rack (>= 1.1.3)
     rack-mount (0.8.3)
       rack (>= 1.0.0)
@@ -359,13 +359,14 @@ GEM
     rails-dev-tweaks (0.6.1)
       actionpack (~> 3.1)
       railties (~> 3.1)
-    rails_best_practices (1.13.8)
+    rails_best_practices (1.14.4)
       activesupport
       awesome_print
-      code_analyzer
+      code_analyzer (>= 0.4.3)
       colored
       erubis
       i18n
+      require_all
       ruby-progressbar
     railties (3.2.13)
       actionpack (= 3.2.13)
@@ -405,6 +406,7 @@ GEM
     redis-store (1.1.4)
       redis (>= 2.2)
     ref (1.0.5)
+    require_all (1.3.1)
     rest-client (1.6.7)
       mime-types (>= 1.16)
     rspec (2.13.0)
@@ -429,7 +431,7 @@ GEM
     safe_yaml (0.9.3)
     sanitize (2.0.3)
       nokogiri (>= 1.4.4, < 1.6)
-    sass (3.2.9)
+    sass (3.2.11)
     sass-rails (3.2.6)
       railties (~> 3.2.0)
       sass (>= 3.1.10)
@@ -449,7 +451,7 @@ GEM
       rubyzip
       websocket (~> 1.0.4)
     settingslogic (2.0.9)
-    sexp_processor (4.2.1)
+    sexp_processor (4.3.0)
     shoulda-matchers (2.1.0)
       activesupport (>= 3.0.0)
     sidekiq (2.14.0)
@@ -489,7 +491,9 @@ GEM
     state_machine (1.2.0)
     stringex (1.5.1)
     temple (0.6.5)
-    test_after_commit (0.2.0)
+    term-ansicolor (1.2.2)
+      tins (~> 0.8)
+    test_after_commit (0.2.1)
     therubyracer (0.11.4)
       libv8 (~> 3.11.8.12)
       ref
@@ -509,6 +513,7 @@ GEM
       mime-types (~> 1.19)
       multi_json (~> 1.5)
       twitter-stream (~> 0.1)
+    tins (0.11.0)
     treetop (1.4.14)
       polyglot
       polyglot (>= 0.3.1)
-- 
GitLab


From aae97481ce044c292fbb94a6cbfdb0e1d2ea69a0 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 29 Sep 2013 16:04:57 +0300
Subject: [PATCH 184/248] Respect authorization in Repository API

* dont allow protect/unprotect branches for users without master permissions
* dont allow access to Repository api for guests
---
 lib/api/helpers.rb                     |  4 ++++
 lib/api/repositories.rb                | 30 ++++++++++----------------
 spec/requests/api/repositories_spec.rb | 13 ++++++++++-
 3 files changed, 27 insertions(+), 20 deletions(-)

diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 860848b2995..2b0c672c7fa 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -64,6 +64,10 @@ module API
       end
     end
 
+    def authorize_admin_project
+      authorize! :admin_project, user_project
+    end
+
     def can?(object, action, subject)
       abilities.allowed?(object, action, subject)
     end
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index fef32d3a2fe..c2b229b0172 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -2,6 +2,7 @@ module API
   # Projects API
   class Repositories < Grape::API
     before { authenticate! }
+    before { authorize! :download_code, user_project }
 
     resource :projects do
       helpers do
@@ -44,13 +45,12 @@ module API
       # Example Request:
       #   PUT /projects/:id/repository/branches/:branch/protect
       put ":id/repository/branches/:branch/protect" do
-        @branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
-        not_found! unless @branch
-        protected = user_project.protected_branches.find_by_name(@branch.name)
+        authorize_admin_project
 
-        unless protected
-          user_project.protected_branches.create(name: @branch.name)
-        end
+        @branch = user_project.repository.find_branch(params[:branch])
+        not_found! unless @branch
+        protected_branch = user_project.protected_branches.find_by_name(@branch.name)
+        user_project.protected_branches.create(name: @branch.name) unless protected_branch
 
         present @branch, with: Entities::RepoObject, project: user_project
       end
@@ -63,13 +63,12 @@ module API
       # Example Request:
       #   PUT /projects/:id/repository/branches/:branch/unprotect
       put ":id/repository/branches/:branch/unprotect" do
-        @branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
-        not_found! unless @branch
-        protected = user_project.protected_branches.find_by_name(@branch.name)
+        authorize_admin_project
 
-        if protected
-          protected.destroy
-        end
+        @branch = user_project.repository.find_branch(params[:branch])
+        not_found! unless @branch
+        protected_branch = user_project.protected_branches.find_by_name(@branch.name)
+        protected_branch.destroy if protected_branch
 
         present @branch, with: Entities::RepoObject, project: user_project
       end
@@ -92,8 +91,6 @@ module API
       # Example Request:
       #   GET /projects/:id/repository/commits
       get ":id/repository/commits" do
-        authorize! :download_code, user_project
-
         page = (params[:page] || 0).to_i
         per_page = (params[:per_page] || 20).to_i
         ref = params[:ref_name] || user_project.try(:default_branch) || 'master'
@@ -110,7 +107,6 @@ module API
       # Example Request:
       #   GET /projects/:id/repository/commits/:sha
       get ":id/repository/commits/:sha" do
-        authorize! :download_code, user_project
         sha = params[:sha]
         commit = user_project.repository.commit(sha)
         not_found! "Commit" unless commit
@@ -125,7 +121,6 @@ module API
       # Example Request:
       #   GET /projects/:id/repository/commits/:sha/diff
       get ":id/repository/commits/:sha/diff" do
-        authorize! :download_code, user_project
         sha = params[:sha]
         result = CommitLoadContext.new(user_project, current_user, {id: sha}).execute
         not_found! "Commit" unless result[:commit]
@@ -140,8 +135,6 @@ module API
       # Example Request:
       #   GET /projects/:id/repository/tree
       get ":id/repository/tree" do
-        authorize! :download_code, user_project
-
         ref = params[:ref_name] || user_project.try(:default_branch) || 'master'
         path = params[:path] || nil
 
@@ -166,7 +159,6 @@ module API
       # Example Request:
       #   GET /projects/:id/repository/blobs/:sha
       get [ ":id/repository/blobs/:sha", ":id/repository/commits/:sha/blob" ] do
-        authorize! :download_code, user_project
         required_attributes! [:filepath]
 
         ref = params[:sha]
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index f15abdd3581..2e509ea2933 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -8,7 +8,8 @@ describe API::API do
   let(:user) { create(:user) }
   let(:user2) { create(:user) }
   let!(:project) { create(:project_with_code, creator_id: user.id) }
-  let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
+  let!(:master) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
+  let!(:guest) { create(:users_project, user: user2, project: project, project_access: UsersProject::GUEST) }
 
   before { project.team << [user, :reporter] }
 
@@ -32,6 +33,11 @@ describe API::API do
       json_response['protected'].should == false
     end
 
+    it "should return a 403 error if guest" do
+      get api("/projects/#{project.id}/repository/branches", user2)
+      response.status.should == 403
+    end
+
     it "should return a 404 error if branch is not available" do
       get api("/projects/#{project.id}/repository/branches/unknown", user)
       response.status.should == 404
@@ -53,6 +59,11 @@ describe API::API do
       response.status.should == 404
     end
 
+    it "should return a 403 error if guest" do
+      put api("/projects/#{project.id}/repository/branches/new_design/protect", user2)
+      response.status.should == 403
+    end
+
     it "should return success when protect branch again" do
       put api("/projects/#{project.id}/repository/branches/new_design/protect", user)
       put api("/projects/#{project.id}/repository/branches/new_design/protect", user)
-- 
GitLab


From 4fc94c679bbfee7da32917bd552f2410774afa17 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 29 Sep 2013 17:43:33 +0300
Subject: [PATCH 185/248] gitlab:test rake task now includes jasmine and db
 setup

---
 lib/tasks/gitlab/test.rake | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/lib/tasks/gitlab/test.rake b/lib/tasks/gitlab/test.rake
index 03b3fc5ea20..38fa8b1a208 100644
--- a/lib/tasks/gitlab/test.rake
+++ b/lib/tasks/gitlab/test.rake
@@ -1,4 +1,11 @@
 namespace :gitlab do
-  desc "GITLAB | Run both spinach and rspec"
-  task test: ['spinach', 'spec']
+  desc "GITLAB | Run all tests"
+  task :test do
+    Rails.env = "test"
+    Rake::Task["db:setup"].invoke
+    Rake::Task["db:seed_fu"].invoke
+    Rake::Task["spinach"].invoke
+    Rake::Task["spec"].invoke
+    Rake::Task["jasmince:ci"].invoke
+  end
 end
-- 
GitLab


From 833b8331a5675b2f6e98a0cd2e22e038b71869bb Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 29 Sep 2013 17:43:59 +0300
Subject: [PATCH 186/248] Use phantomjs for jasmine tests. Fixed broken one

---
 .../stat_graph_contributors_util_spec.js      | 53 ++++++++++---------
 spec/javascripts/support/jasmine_helper.rb    | 14 ++---
 2 files changed, 32 insertions(+), 35 deletions(-)

diff --git a/spec/javascripts/stat_graph_contributors_util_spec.js b/spec/javascripts/stat_graph_contributors_util_spec.js
index 367f0af05f8..2e52479ccbb 100644
--- a/spec/javascripts/stat_graph_contributors_util_spec.js
+++ b/spec/javascripts/stat_graph_contributors_util_spec.js
@@ -3,10 +3,10 @@ describe("ContributorsStatGraphUtil", function () {
   describe("#parse_log", function () {
     it("returns a correctly parsed log", function () {
       var fake_log = [
-            {author: "Karlo Soriano", date: "2013-05-09", additions: 471},
-            {author: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 6, deletions: 1},
-            {author: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 19, deletions: 3},
-            {author: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 29, deletions: 3}]
+            {author_email: "karlo@email.com", author_name: "Karlo Soriano", date: "2013-05-09", additions: 471},
+            {author_email: "dzaporozhets@email.com", author_name: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 6, deletions: 1},
+            {author_email: "dzaporozhets@email.com", author_name: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 19, deletions: 3},
+            {author_email: "dzaporozhets@email.com", author_name: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 29, deletions: 3}]
       
       var correct_parsed_log = {
         total: [
@@ -15,11 +15,11 @@ describe("ContributorsStatGraphUtil", function () {
         by_author:
         [
         { 
-          author: "Karlo Soriano", 
+          author_name: "Karlo Soriano", author_email: "karlo@email.com",
           "2013-05-09": {date: "2013-05-09", additions: 471, deletions: 0, commits: 1}
         },
         {
-          author: "Dmitriy Zaporozhets",
+          author_name: "Dmitriy Zaporozhets",author_email: "dzaporozhets@email.com",
           "2013-05-08": {date: "2013-05-08", additions: 54, deletions: 7, commits: 3}
         }
         ]
@@ -112,10 +112,10 @@ describe("ContributorsStatGraphUtil", function () {
 
   describe("#add_author", function () {
     it("adds an author field to the collection", function () {
-      var fake_author = "Author"
+      var fake_author = { author_name: "Author", author_email: 'fake@email.com' }
       var fake_collection = {}
       ContributorsStatGraphUtil.add_author(fake_author, fake_collection)
-      expect(fake_collection[fake_author].author).toEqual("Author")
+      expect(fake_collection[fake_author.author_name].author_name).toEqual("Author")
     })
   })
 
@@ -153,30 +153,35 @@ describe("ContributorsStatGraphUtil", function () {
   describe("#get_author_data", function () {
     it("returns the log by author sorted by specified field", function () {
       var fake_parsed_log = {
-      total: [{date: "2013-05-09", additions: 471, deletions: 0, commits: 1},
-      {date: "2013-05-08", additions: 54, deletions: 7, commits: 3}],
-      by_author:[
-      { 
-        author: "Karlo Soriano", 
-        "2013-05-09": {date: "2013-05-09", additions: 471, deletions: 0, commits: 1}
-      },
-      {
-        author: "Dmitriy Zaporozhets",
-        "2013-05-08": {date: "2013-05-08", additions: 54, deletions: 7, commits: 3}
+        total: [
+          {date: "2013-05-09", additions: 471, deletions: 0, commits: 1}, 
+          {date: "2013-05-08", additions: 54, deletions: 7, commits: 3}
+        ],
+        by_author: [
+          { 
+            author_name: "Karlo Soriano", author_email: "karlo@email.com",
+            "2013-05-09": {date: "2013-05-09", additions: 471, deletions: 0, commits: 1}
+          },
+          {
+            author_name: "Dmitriy Zaporozhets", author_email: "dzaporozhets@email.com",
+            "2013-05-08": {date: "2013-05-08", additions: 54, deletions: 7, commits: 3}
+          }
+        ]
       }
-      ]}
-      var correct_author_data = [{author:"Dmitriy Zaporozhets",dates:{"2013-05-08":3},deletions:7,additions:54,"commits":3},
-      {author:"Karlo Soriano",dates:{"2013-05-09":1},deletions:0,additions:471,commits:1}]
+      var correct_author_data = [
+        {author_name:"Dmitriy Zaporozhets",author_email:"dzaporozhets@email.com",dates:{"2013-05-08":3},deletions:7,additions:54,"commits":3},
+        {author_name:"Karlo Soriano",author_email:"karlo@email.com",dates:{"2013-05-09":1},deletions:0,additions:471,commits:1}
+      ]
       expect(ContributorsStatGraphUtil.get_author_data(fake_parsed_log, "commits")).toEqual(correct_author_data)
     })
   })
 
   describe("#parse_log_entry", function () {
     it("adds the corresponding info from the log entry to the author", function () {
-      var fake_log_entry =    { author: "Karlo Soriano", 
+      var fake_log_entry =    { author_name: "Karlo Soriano", author_email: "karlo@email.com",
         "2013-05-09": {date: "2013-05-09", additions: 471, deletions: 0, commits: 1}
       }
-      var correct_parsed_log = {author:"Karlo Soriano",dates:{"2013-05-09":1},deletions:0,additions:471,commits:1}
+      var correct_parsed_log = {author_name:"Karlo Soriano",author_email:"karlo@email.com",dates:{"2013-05-09":1},deletions:0,additions:471,commits:1}
       expect(ContributorsStatGraphUtil.parse_log_entry(fake_log_entry, 'commits', null)).toEqual(correct_parsed_log)
     })
   })
@@ -197,4 +202,4 @@ describe("ContributorsStatGraphUtil", function () {
   })
 
 
-})
\ No newline at end of file
+})
diff --git a/spec/javascripts/support/jasmine_helper.rb b/spec/javascripts/support/jasmine_helper.rb
index 986a4c16f3e..13e55023b4c 100644
--- a/spec/javascripts/support/jasmine_helper.rb
+++ b/spec/javascripts/support/jasmine_helper.rb
@@ -1,11 +1,3 @@
-#Use this file to set/override Jasmine configuration options
-#You can remove it if you don't need it.
-#This file is loaded *after* jasmine.yml is interpreted.
-#
-#Example: using a different boot file.
-#Jasmine.configure do |config|
-#   @config.boot_dir = '/absolute/path/to/boot_dir'
-#   @config.boot_files = lambda { ['/absolute/path/to/boot_dir/file.js'] }
-#end
-#
-
+Jasmine.configure do |config|
+  config.browser = :phantomjs
+end
-- 
GitLab


From 88ee95b00a02750844a3f540fee9a942f0c23466 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 29 Sep 2013 17:45:43 +0300
Subject: [PATCH 187/248] Use gitlab:test for travis-ci

---
 .travis.yml           | 5 +----
 lib/tasks/travis.rake | 5 -----
 2 files changed, 1 insertion(+), 9 deletions(-)
 delete mode 100644 lib/tasks/travis.rake

diff --git a/.travis.yml b/.travis.yml
index 3ed3dec1425..f0fc2fb8829 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,7 +15,4 @@ services:
 before_script:
   - "cp config/database.yml.$DB config/database.yml"
   - "cp config/gitlab.yml.example config/gitlab.yml"
-  - "bundle exec rake db:setup RAILS_ENV=test"
-  - "bundle exec rake db:seed_fu RAILS_ENV=test"
-  - "sh -e /etc/init.d/xvfb start"
-script: "bundle exec rake travis --trace"
+script: "bundle exec rake gitlab:test --trace"
diff --git a/lib/tasks/travis.rake b/lib/tasks/travis.rake
deleted file mode 100644
index bc1b8aadbc5..00000000000
--- a/lib/tasks/travis.rake
+++ /dev/null
@@ -1,5 +0,0 @@
-desc "Travis run tests"
-task travis: [
-  :spinach,
-  :spec
-]
-- 
GitLab


From 42eb4222b066bef2d464bdd0ecbd362edfd7ef24 Mon Sep 17 00:00:00 2001
From: Boyan Tabakov <boyan.tabakov@futurice.com>
Date: Sun, 29 Sep 2013 19:55:09 +0300
Subject: [PATCH 188/248] Added test cases to verify admin status of users
 created via API.

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

diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 4a299d3d958..4ef78b8e5d0 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -62,6 +62,25 @@ describe API::API do
       new_user.can_create_group.should == true
     end
 
+    it "should create non-admin user" do
+      post api('/users', admin), attributes_for(:user, admin: false, can_create_group: false)
+      response.status.should == 201
+      user_id = json_response['id']
+      new_user = User.find(user_id)
+      new_user.should_not == nil
+      new_user.admin.should == false
+      new_user.can_create_group.should == false
+    end
+
+    it "should create non-admin users by default" do
+      post api('/users', admin), attributes_for(:user)
+      response.status.should == 201
+      user_id = json_response['id']
+      new_user = User.find(user_id)
+      new_user.should_not == nil
+      new_user.admin.should == false
+    end
+
     it "should return 201 Created on success" do
       post api("/users", admin), attributes_for(:user, projects_limit: 3)
       response.status.should == 201
-- 
GitLab


From c1451db05b6b2c7244300191974c4a8ac88787bd Mon Sep 17 00:00:00 2001
From: Boyan Tabakov <boyan.tabakov@futurice.com>
Date: Mon, 19 Aug 2013 12:11:36 +0300
Subject: [PATCH 189/248] Added Flowdock integration support via a service.

Added test for the FlowdockService.
---
 Gemfile                                    |  3 ++
 Gemfile.lock                               |  8 ++++
 app/models/flowdock_service.rb             | 50 ++++++++++++++++++++++
 app/models/project.rb                      |  3 +-
 features/project/service.feature           |  6 +++
 features/steps/project/project_services.rb | 14 ++++++
 spec/models/flowdock_service_spec.rb       | 48 +++++++++++++++++++++
 7 files changed, 131 insertions(+), 1 deletion(-)
 create mode 100644 app/models/flowdock_service.rb
 create mode 100644 spec/models/flowdock_service_spec.rb

diff --git a/Gemfile b/Gemfile
index 6530139cf5f..b38c0615589 100644
--- a/Gemfile
+++ b/Gemfile
@@ -111,6 +111,9 @@ gem 'tinder', '~> 1.9.2'
 # HipChat integration
 gem "hipchat", "~> 0.9.0"
 
+# Flowdock integration
+gem "flowdock-git-hook", "~> 0.4.2"
+
 # d3
 gem "d3_rails", "~> 3.1.4"
 
diff --git a/Gemfile.lock b/Gemfile.lock
index 59d67d4efe9..1bc13fffb68 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -135,6 +135,9 @@ GEM
       faraday (>= 0.7.4, < 0.9)
     ffaker (1.18.0)
     ffi (1.9.0)
+    flowdock-git-hook (0.4.2)
+      grit (>= 2.4.1)
+      multi_json
     fog (1.3.1)
       builder
       excon (~> 0.13.0)
@@ -205,6 +208,10 @@ GEM
     grape-entity (0.3.0)
       activesupport
       multi_json (>= 1.3.2)
+    grit (2.5.0)
+      diff-lcs (~> 1.1)
+      mime-types (~> 1.15)
+      posix-spawn (~> 0.3.6)
     growl (1.0.3)
     guard (1.8.1)
       formatador (>= 0.2.4)
@@ -570,6 +577,7 @@ DEPENDENCIES
   enumerize
   factory_girl_rails
   ffaker
+  flowdock-git-hook (~> 0.4.2)
   fog (~> 1.3.1)
   font-awesome-rails
   foreman
diff --git a/app/models/flowdock_service.rb b/app/models/flowdock_service.rb
new file mode 100644
index 00000000000..143e986ca75
--- /dev/null
+++ b/app/models/flowdock_service.rb
@@ -0,0 +1,50 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id          :integer          not null, primary key
+#  type        :string(255)
+#  title       :string(255)
+#  token       :string(255)
+#  project_id  :integer          not null
+#  created_at  :datetime         not null
+#  updated_at  :datetime         not null
+#  active      :boolean          default(FALSE), not null
+#  project_url :string(255)
+#
+
+class FlowdockService < Service
+  validates :token, presence: true, if: :activated?
+
+  def title
+    'Flowdock'
+  end
+
+  def description
+    'Flowdock is a collaboration web app for technical teams.'
+  end
+
+  def to_param
+    'flowdock'
+  end
+
+  def fields
+    [
+      { type: 'text', name: 'token',     placeholder: '' }
+    ]
+  end
+
+  def execute(push_data)
+    repo_path = File.join(Gitlab.config.gitlab_shell.repos_path, "#{project.path_with_namespace}.git")
+    Flowdock::Git.post(
+      push_data[:ref],
+      push_data[:before],
+      push_data[:after],
+      token: token,
+      repo: repo_path,
+      repo_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}",
+      commit_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/%s",
+      diff_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/compare/%s...%s",
+      )
+  end
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index c4f4b06713d..49802fa1720 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -48,6 +48,7 @@ class Project < ActiveRecord::Base
   has_one :campfire_service, dependent: :destroy
   has_one :pivotaltracker_service, dependent: :destroy
   has_one :hipchat_service, dependent: :destroy
+  has_one :flowdock_service, dependent: :destroy
   has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
   has_one :forked_from_project, through: :forked_project_link
 
@@ -221,7 +222,7 @@ class Project < ActiveRecord::Base
   end
 
   def available_services_names
-    %w(gitlab_ci campfire hipchat pivotaltracker)
+    %w(gitlab_ci campfire hipchat pivotaltracker flowdock)
   end
 
   def gitlab_ci?
diff --git a/features/project/service.feature b/features/project/service.feature
index e685c385d1d..4805d2befbe 100644
--- a/features/project/service.feature
+++ b/features/project/service.feature
@@ -24,3 +24,9 @@ Feature: Project Services
     And I click pivotaltracker service link
     And I fill pivotaltracker settings
     Then I should see pivotaltracker service settings saved
+
+  Scenario: Activate Flowdock service
+    When I visit project "Shop" services page
+    And I click Flowdock service link
+    And I fill Flowdock settings
+    Then I should see Flowdock service settings saved
diff --git a/features/steps/project/project_services.rb b/features/steps/project/project_services.rb
index a24100ff8c0..70eafc875d4 100644
--- a/features/steps/project/project_services.rb
+++ b/features/steps/project/project_services.rb
@@ -58,4 +58,18 @@ class ProjectServices < Spinach::FeatureSteps
   Then 'I should see pivotaltracker service settings saved' do
     find_field('Token').value.should == 'verySecret'
   end
+
+  And 'I click Flowdock service link' do
+    click_link 'Flowdock'
+  end
+
+  And 'I fill Flowdock settings' do
+    check 'Active'
+    fill_in 'Token', with: 'verySecret'
+    click_button 'Save'
+  end
+
+  Then 'I should see Flowdock service settings saved' do
+    find_field('Token').value.should == 'verySecret'
+  end
 end
diff --git a/spec/models/flowdock_service_spec.rb b/spec/models/flowdock_service_spec.rb
new file mode 100644
index 00000000000..b22193c9e93
--- /dev/null
+++ b/spec/models/flowdock_service_spec.rb
@@ -0,0 +1,48 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id          :integer          not null, primary key
+#  type        :string(255)
+#  title       :string(255)
+#  token       :string(255)
+#  project_id  :integer          not null
+#  created_at  :datetime         not null
+#  updated_at  :datetime         not null
+#  active      :boolean          default(FALSE), not null
+#  project_url :string(255)
+#
+
+require 'spec_helper'
+
+describe FlowdockService do
+  describe "Associations" do
+    it { should belong_to :project }
+    it { should have_one :service_hook }
+  end
+
+  describe "Execute" do
+    let(:user)    { create(:user) }
+    let(:project) { create(:project_with_code) }
+
+    before do
+      @flowdock_service = FlowdockService.new
+      @flowdock_service.stub(
+        project_id: project.id,
+        project: project,
+        service_hook: true,
+        token: 'verySecret'
+      )
+      @sample_data = GitPushService.new.sample_data(project, user)
+      @api_url = 'https://api.flowdock.com/v1/git/verySecret'
+      WebMock.stub_request(:post, @api_url)
+    end
+
+    it "should call FlowDock API" do
+      @flowdock_service.execute(@sample_data)
+      WebMock.should have_requested(:post, @api_url).with(
+        body: /#{@sample_data[:before]}.*#{@sample_data[:after]}.*#{project.path}/
+      ).once
+    end
+  end
+end
-- 
GitLab


From 53990397dd9bdbfd400401b4d0c415670c761973 Mon Sep 17 00:00:00 2001
From: Thomas Misilo <misilot@fit.edu>
Date: Sun, 29 Sep 2013 13:46:02 -0400
Subject: [PATCH 190/248] Changed wording in application.rb and
 gitlab.yml.example to match unicorn.rb. This is for when using a non-root
 path

---
 config/application.rb     | 4 ++--
 config/gitlab.yml.example | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/config/application.rb b/config/application.rb
index 6ddc87010b3..cad7cb4ac5f 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -70,11 +70,11 @@ module Gitlab
     config.assets.version = '1.0'
 
     # Uncomment and customize the last line to run in a non-root path
-    # WARNING: This feature is no longer supported
+    # WARNING: This feature is known to work, but unsupported
     # Note that three settings need to be changed for this to work.
     # 1) In your application.rb file: config.relative_url_root = "/gitlab"
     # 2) In your gitlab.yml file: relative_url_root: /gitlab
-    # 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT']
+    # 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
     #
     # config.relative_url_root = "/gitlab"
 
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index ee29d52815c..60a21f673f4 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -20,11 +20,11 @@ production: &base
     https: false
 
     # Uncomment and customize the last line to run in a non-root path
-    # WARNING: This feature is no longer supported
+    # WARNING: This feature is known to work, but unsupported
     # Note that three settings need to be changed for this to work.
     # 1) In your application.rb file: config.relative_url_root = "/gitlab"
     # 2) In your gitlab.yml file: relative_url_root: /gitlab
-    # 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT']
+    # 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
     #
     # relative_url_root: /gitlab
 
-- 
GitLab


From e35d355b2cf6c2dc8f0774bb282ce33bb76b702e Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 29 Sep 2013 23:36:44 +0300
Subject: [PATCH 191/248] Make rake gitlab:test works

---
 lib/tasks/gitlab/test.rake                 | 19 +++++++++++++------
 spec/javascripts/support/jasmine_helper.rb |  2 ++
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/lib/tasks/gitlab/test.rake b/lib/tasks/gitlab/test.rake
index 38fa8b1a208..011748c9711 100644
--- a/lib/tasks/gitlab/test.rake
+++ b/lib/tasks/gitlab/test.rake
@@ -1,11 +1,18 @@
 namespace :gitlab do
   desc "GITLAB | Run all tests"
   task :test do
-    Rails.env = "test"
-    Rake::Task["db:setup"].invoke
-    Rake::Task["db:seed_fu"].invoke
-    Rake::Task["spinach"].invoke
-    Rake::Task["spec"].invoke
-    Rake::Task["jasmince:ci"].invoke
+    cmds = [
+      "rake db:setup",
+      "rake db:seed_fu",
+      "rake spinach",
+      "rake spec",
+      "rake jasmine:ci"
+    ]
+
+    cmds.each do |cmd|
+      system(cmd + " RAILS_ENV=test")
+
+      raise "#{cmd} failed!" unless $?.exitstatus.zero?
+    end
   end
 end
diff --git a/spec/javascripts/support/jasmine_helper.rb b/spec/javascripts/support/jasmine_helper.rb
index 13e55023b4c..34b418a9ca3 100644
--- a/spec/javascripts/support/jasmine_helper.rb
+++ b/spec/javascripts/support/jasmine_helper.rb
@@ -1,3 +1,5 @@
+WebMock.allow_net_connect!
+
 Jasmine.configure do |config|
   config.browser = :phantomjs
 end
-- 
GitLab


From 8c73542bc8623c908af1ae3000a7e887edfd5d7a Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 30 Sep 2013 09:27:45 +0300
Subject: [PATCH 192/248] Add more entries to 6.2.0 CHANGELOG

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

diff --git a/CHANGELOG b/CHANGELOG
index 3db03f76ed7..c1107717fc8 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,17 @@
 v 6.2.0
   - Public projects are visible from the outside
+  - Add group access to permissions page
+  - Require current password to change one
+  - Group owner or admin can remove other group owners
+  - Remove group transfer since we have multiple owners
+  - Respect authorization in Repository API
+  - Improve UI for Project#files page
+  - Add more security specs
+  - Added search for projects by name to api (Izaak Alpert)
+  - Make default user theme configurable (Izaak Alpert)
+  - Update logic for validates_merge_request for tree of MR (Andrew Kumanyaev)
+  - Rake tasks for web hooks management (Jonhnny Weslley)
+  - Extended User API to expose admin and can_create_group for user creation/updating (Boyan Tabakov)
 
 v 6.1.0
   - Project specific IDs for issues, mr, milestones
-- 
GitLab


From 5df237914285d4f7bc7607be0ae263ccec63a484 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 30 Sep 2013 09:50:30 +0300
Subject: [PATCH 193/248] Few UI fixes for notes

---
 app/assets/stylesheets/sections/notes.scss | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss
index bae1ac3aa9a..94b9ca3b181 100644
--- a/app/assets/stylesheets/sections/notes.scss
+++ b/app/assets/stylesheets/sections/notes.scss
@@ -135,11 +135,15 @@ ul.notes {
       background-color: $white;
       border-width: 1px 0;
       padding-top: 0;
+
+      li {
+        padding: 5px;
+      }
     }
   }
 
   .reply-btn {
-    margin-top: 8px;
+    margin: 5px;
   }
 }
 
-- 
GitLab


From f1863b91d6a2b3d261ea89d70a3b32e0b0658204 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 30 Sep 2013 09:55:48 +0300
Subject: [PATCH 194/248] Fix Api session spec

---
 spec/requests/api/session_spec.rb | 1 -
 1 file changed, 1 deletion(-)

diff --git a/spec/requests/api/session_spec.rb b/spec/requests/api/session_spec.rb
index 88c17f26a69..0fd90c567e0 100644
--- a/spec/requests/api/session_spec.rb
+++ b/spec/requests/api/session_spec.rb
@@ -14,7 +14,6 @@ describe API::API do
         json_response['email'].should == user.email
         json_response['private_token'].should == user.private_token
         json_response['is_admin'].should == user.is_admin?
-        json_response['can_create_team'].should == user.can_create_team?
         json_response['can_create_project'].should == user.can_create_project?
         json_response['can_create_group'].should == user.can_create_group?
       end
-- 
GitLab


From d2645f65535587c8d24a23cbbc9c7fa77f4e3f27 Mon Sep 17 00:00:00 2001
From: Tobias Bieniek <Tobias.Bieniek@gmx.de>
Date: Mon, 30 Sep 2013 11:01:57 +0200
Subject: [PATCH 195/248] Fixed typo in groups.md

---
 doc/api/groups.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/api/groups.md b/doc/api/groups.md
index 9c551fff83a..fb77901c65b 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -54,7 +54,7 @@ POST  /groups/:id/projects/:project_id
 
 Parameters:
 + `id` (required) - The ID of a group
-+ `project_id (required) - The ID of a project
++ `project_id` (required) - The ID of a project
 
 
 ## Group members
-- 
GitLab


From 62fe0e2435daf1abd235b185212a829612408985 Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Thu, 26 Sep 2013 22:40:55 +0200
Subject: [PATCH 196/248] Add documentation to help section, rack_attack as
 example

---
 .gitignore                                 |  1 +
 app/views/help/_layout.html.haml           |  3 +++
 app/views/help/index.html.haml             |  4 ++++
 app/views/help/security.html.haml          | 15 +++++++++++++++
 config/application.rb                      |  4 ++--
 config/initializers/rack_attack.rb         |  3 ---
 config/initializers/rack_attack.rb.example | 16 ++++++++++++++++
 config/routes.rb                           |  1 +
 doc/security/rack_attack.md                | 19 +++++++++++++++++++
 9 files changed, 61 insertions(+), 5 deletions(-)
 create mode 100644 app/views/help/security.html.haml
 delete mode 100644 config/initializers/rack_attack.rb
 create mode 100644 config/initializers/rack_attack.rb.example
 create mode 100644 doc/security/rack_attack.md

diff --git a/.gitignore b/.gitignore
index 683e6c45a2b..084edd30df7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@ Vagrantfile
 config/gitlab.yml
 config/database.yml
 config/initializers/omniauth.rb
+config/initializers/rack_attack.rb
 config/unicorn.rb
 config/resque.yml
 config/aws.yml
diff --git a/app/views/help/_layout.html.haml b/app/views/help/_layout.html.haml
index ac8660dcbb4..da917888eee 100644
--- a/app/views/help/_layout.html.haml
+++ b/app/views/help/_layout.html.haml
@@ -30,5 +30,8 @@
         %li
           %strong= link_to "Public Access", help_public_access_path
 
+        %li
+          %strong= link_to "Security", help_security_path
+
   .span9.pull-right
     = yield
diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml
index ff01136f5bb..fadc2dc21cb 100644
--- a/app/views/help/index.html.haml
+++ b/app/views/help/index.html.haml
@@ -79,3 +79,7 @@
         %li
           %strong= link_to "Public Access", help_public_access_path
           %p Learn how you can allow public access to a project.
+
+        %li
+          %strong= link_to "Security", help_security_path
+          %p Learn what you can do to secure your GitLab instance.
diff --git a/app/views/help/security.html.haml b/app/views/help/security.html.haml
new file mode 100644
index 00000000000..72f21e9f634
--- /dev/null
+++ b/app/views/help/security.html.haml
@@ -0,0 +1,15 @@
+= render layout: 'help/layout' do
+  %h3.page-title Security
+
+  %p.slead
+    If your GitLab instance is visible from the internet chances are it will be 'tested' by bots sooner or later.
+    %br
+    %br
+    %br
+    .file-holder
+      .file-title
+        %i.icon-file
+        Dealing with bruteforcing
+      .file-content.wiki
+        = preserve do
+          = markdown File.read(Rails.root.join("doc", "security", "rack_attack.md"))
diff --git a/config/application.rb b/config/application.rb
index cad7cb4ac5f..d85bcab7885 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -78,7 +78,7 @@ module Gitlab
     #
     # config.relative_url_root = "/gitlab"
 
-    # Enable rack attack middleware
-    config.middleware.use Rack::Attack
+    # Uncomment to enable rack attack middleware
+    # config.middleware.use Rack::Attack
   end
 end
diff --git a/config/initializers/rack_attack.rb b/config/initializers/rack_attack.rb
deleted file mode 100644
index 88e638ba118..00000000000
--- a/config/initializers/rack_attack.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-Rack::Attack.throttle('user logins, registration and password reset', limit: 6, period: 60.seconds) do |req|
-  req.ip if ["/users/password", "/users/sign_in", "/users"].include?(req.path) && req.post?
-end
diff --git a/config/initializers/rack_attack.rb.example b/config/initializers/rack_attack.rb.example
new file mode 100644
index 00000000000..76fa7ad282e
--- /dev/null
+++ b/config/initializers/rack_attack.rb.example
@@ -0,0 +1,16 @@
+# To enable rack-attack for your GitLab instance do the following:
+# 1. In config/application.rb find and uncomment the following line:
+# config.middleware.use Rack::Attack
+# 2. Rename this file to rack_attack.rb
+# 3. Review the paths_to_be_protected and add any other path you need protecting
+# 4. Restart GitLab instance
+#
+
+paths_to_be_protected = [
+  "#{Rails.application.config.relative_url_root}/users/password",
+  "#{Rails.application.config.relative_url_root}/users/sign_in",
+  "#{Rails.application.config.relative_url_root}/users"
+]
+Rack::Attack.throttle('protected paths', limit: 6, period: 60.seconds) do |req|
+  req.ip if paths_to_be_protected.include?(req.path) && req.post?
+end
diff --git a/config/routes.rb b/config/routes.rb
index 9d47faa19d5..612a7327ec5 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -39,6 +39,7 @@ Gitlab::Application.routes.draw do
   get 'help/web_hooks'      => 'help#web_hooks'
   get 'help/workflow'       => 'help#workflow'
   get 'help/shortcuts'
+  get 'help/security'
 
   #
   # Global snippets
diff --git a/doc/security/rack_attack.md b/doc/security/rack_attack.md
new file mode 100644
index 00000000000..a0d02b1650f
--- /dev/null
+++ b/doc/security/rack_attack.md
@@ -0,0 +1,19 @@
+To prevent abusive clients doing damage GitLab uses rack-attack gem.
+If you installed or upgraded GitLab by following the official guides this should be enabled by default.
+If you are missing `config/initializers/rack_attack.rb` the following steps need to be taken in order to enable protection for your GitLab instance:
+
+1. In config/application.rb find and uncomment the following line:
+  config.middleware.use Rack::Attack
+2. Rename config/initializers/rack_attack.rb.example to config/initializers/rack_attack.rb
+3. Review the paths_to_be_protected and add any other path you need protecting
+4. Restart GitLab instance
+
+By default, user sign-in, user sign-up(if enabled) and user password reset is limited to 6 requests per minute.
+After trying for 6 times, client will have to wait for the next minute to be able to try again.
+These settings can be found in `config/initializers/rack_attack.rb`
+
+If you want more restrictive/relaxed throttle rule change the `limit` or `period` values. For example, more relaxed throttle rule will be if you set limit: 3 and period: 1.second(this will allow 3 requests per second). You can also add other paths to the protected list by adding to `paths_to_be_protected` variable. If you change any of these settings do not forget to restart your GitLab instance.
+
+In case you find throttling is not enough to protect you against abusive clients, rack-attack gem offers IP whitelisting, blacklisting, Fail2ban style filter and tracking.
+
+For more information on how to use these options check out [rack-attack README](https://github.com/kickstarter/rack-attack/blob/master/README.md).
\ No newline at end of file
-- 
GitLab


From f49e18c991774a7fb0942f0d2cf2f092ce9575ce Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 30 Sep 2013 13:59:16 +0300
Subject: [PATCH 197/248] Remove grit require

---
 app/models/network/commit.rb | 2 --
 app/models/project.rb        | 2 --
 2 files changed, 4 deletions(-)

diff --git a/app/models/network/commit.rb b/app/models/network/commit.rb
index e31adcebbe7..8417f200e36 100644
--- a/app/models/network/commit.rb
+++ b/app/models/network/commit.rb
@@ -1,5 +1,3 @@
-require "grit"
-
 module Network
   class Commit
     include ActionView::Helpers::TagHelper
diff --git a/app/models/project.rb b/app/models/project.rb
index 49802fa1720..8755ffa69b8 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -24,8 +24,6 @@
 #  import_url             :string(255)
 #
 
-require "grit"
-
 class Project < ActiveRecord::Base
   include Gitlab::ShellAdapter
   extend Enumerize
-- 
GitLab


From c00cd658d5d045507d4fb59536d8468a72c0cf09 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 30 Sep 2013 16:47:26 +0300
Subject: [PATCH 198/248] API: Protect project deploy keys from unauthorized
 access

---
 lib/api/deploy_keys.rb | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb
index 55c947eb176..218b3d8eee2 100644
--- a/lib/api/deploy_keys.rb
+++ b/lib/api/deploy_keys.rb
@@ -2,6 +2,7 @@ module API
   # Projects API
   class DeployKeys < Grape::API
     before { authenticate! }
+    before { authorize_admin_project }
 
     resource :projects do
       helpers do
-- 
GitLab


From 13280d8b8c86fd5a0489fcaf03425c99fd4ab943 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 30 Sep 2013 16:49:55 +0300
Subject: [PATCH 199/248] Refactor API: project hooks

---
 lib/api/project_hooks.rb | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb
index 28501256795..738974955f3 100644
--- a/lib/api/project_hooks.rb
+++ b/lib/api/project_hooks.rb
@@ -2,6 +2,7 @@ module API
   # Projects API
   class ProjectHooks < Grape::API
     before { authenticate! }
+    before { authorize_admin_project }
 
     resource :projects do
       helpers do
@@ -20,7 +21,6 @@ module API
       # Example Request:
       #   GET /projects/:id/hooks
       get ":id/hooks" do
-        authorize! :admin_project, user_project
         @hooks = paginate user_project.hooks
         present @hooks, with: Entities::Hook
       end
@@ -33,7 +33,6 @@ module API
       # Example Request:
       #   GET /projects/:id/hooks/:hook_id
       get ":id/hooks/:hook_id" do
-        authorize! :admin_project, user_project
         @hook = user_project.hooks.find(params[:hook_id])
         present @hook, with: Entities::Hook
       end
@@ -47,7 +46,6 @@ module API
       # Example Request:
       #   POST /projects/:id/hooks
       post ":id/hooks" do
-        authorize! :admin_project, user_project
         required_attributes! [:url]
 
         @hook = user_project.hooks.new({"url" => params[:url]})
@@ -71,7 +69,6 @@ module API
       #   PUT /projects/:id/hooks/:hook_id
       put ":id/hooks/:hook_id" do
         @hook = user_project.hooks.find(params[:hook_id])
-        authorize! :admin_project, user_project
         required_attributes! [:url]
 
         attrs = attributes_for_keys [:url]
@@ -93,7 +90,6 @@ module API
       # Example Request:
       #   DELETE /projects/:id/hooks/:hook_id
       delete ":id/hooks/:hook_id" do
-        authorize! :admin_project, user_project
         required_attributes! [:hook_id]
 
         begin
-- 
GitLab


From 10f27e372faa19dd0f1e8b8f2771ea473b475b08 Mon Sep 17 00:00:00 2001
From: Chris McKnight <cmckni3@gmail.com>
Date: Mon, 30 Sep 2013 17:39:33 -0500
Subject: [PATCH 200/248] Fix invalid json in issues API doc

---
 doc/api/issues.md | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/doc/api/issues.md b/doc/api/issues.md
index 723c8acf381..314268b0fc0 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -25,7 +25,7 @@ GET /issues
       "blocked": false,
       "created_at": "2012-05-23T08:00:58Z"
     },
-    "state": 'closed',
+    "state": "closed",
     "updated_at": "2012-07-02T17:53:12Z",
     "created_at": "2012-07-02T17:53:12Z"
   },
@@ -42,7 +42,7 @@ GET /issues
       "title": "v1.0",
       "description": "",
       "due_date": "2012-07-20",
-      "state": 'reopenend',
+      "state": "reopenend",
       "updated_at": "2012-07-04T13:42:48Z",
       "created_at": "2012-07-04T13:42:48Z"
     },
@@ -62,7 +62,7 @@ GET /issues
       "blocked": false,
       "created_at": "2012-05-23T08:00:58Z"
     },
-    "state": 'opened',
+    "state": "opened",
     "updated_at": "2012-07-12T13:43:19Z",
     "created_at": "2012-06-28T12:58:06Z"
   }
@@ -111,7 +111,7 @@ Parameters:
     "title": "v1.0",
     "description": "",
     "due_date": "2012-07-20",
-    "state": 'closed',
+    "state": "closed",
     "updated_at": "2012-07-04T13:42:48Z",
     "created_at": "2012-07-04T13:42:48Z"
   },
@@ -131,7 +131,7 @@ Parameters:
     "blocked": false,
     "created_at": "2012-05-23T08:00:58Z"
   },
-  "state": 'opened',
+  "state": "opened",
   "updated_at": "2012-07-12T13:43:19Z",
   "created_at": "2012-06-28T12:58:06Z"
 }
@@ -190,4 +190,3 @@ Parameters:
 
 + `id` (required) - The project ID
 + `issue_id` (required) - The ID of the issue
-
-- 
GitLab


From 43d074c0a83b2afff721d553cb7da847b24906b1 Mon Sep 17 00:00:00 2001
From: Chris McKnight <cmckni3@gmail.com>
Date: Mon, 30 Sep 2013 21:45:15 -0500
Subject: [PATCH 201/248] Fix json keys in groups API documentation

---
 doc/api/groups.md | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/doc/api/groups.md b/doc/api/groups.md
index fb77901c65b..47c7c1bf4f5 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -70,22 +70,22 @@ GET /groups/:id/members
 ```json
 [
   {
-    id: 1,
-    username: "raymond_smith",
-    email: "ray@smith.org",
-    name: "Raymond Smith",
-    state: "active",
-    created_at: "2012-10-22T14:13:35Z",
-    access_level: 30
+    "id": 1,
+    "username": "raymond_smith",
+    "email": "ray@smith.org",
+    "name": "Raymond Smith",
+    "state": "active",
+    "created_at": "2012-10-22T14:13:35Z",
+    "access_level": 30
   },
   {
-    id: 2,
-    username: "john_doe",
-    email: "joh@doe.org",
-    name: "John Doe",
-    state: "active",
-    created_at: "2012-10-22T14:13:35Z",
-    access_level: 30
+    "id": 2,
+    "username": "john_doe",
+    "email": "joh@doe.org",
+    "name": "John Doe",
+    "state": "active",
+    "created_at": "2012-10-22T14:13:35Z",
+    "access_level": 30
   }
 ]
 ```
-- 
GitLab


From ecb308f206b5736755f4d5e7856db1e0a8e7161f Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Tue, 1 Oct 2013 10:05:58 +0200
Subject: [PATCH 202/248] Update install/update docs.

---
 doc/install/installation.md |   7 +++
 doc/update/6.1-to-6.2.md    | 100 ++++++++++++++++++++++++++++++++++++
 2 files changed, 107 insertions(+)
 create mode 100644 doc/update/6.1-to-6.2.md

diff --git a/doc/install/installation.md b/doc/install/installation.md
index 71a587d2ee3..03ea5fbb28f 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -195,6 +195,13 @@ You can change `6-1-stable` to `master` if you want the *bleeding edge* version,
     # Ex. change amount of workers to 3 for 2GB RAM server
     sudo -u git -H editor config/unicorn.rb
 
+    # Copy the example Rack attack config
+    sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
+
+    # Enable rack attack middleware
+    # Find and uncomment the line 'config.middleware.use Rack::Attack'
+    sudo -u git -H editor config/application.rb
+
     # Configure Git global settings for git user, useful when editing via web
     # Edit user.email according to what is set in gitlab.yml
     sudo -u git -H git config --global user.name "GitLab"
diff --git a/doc/update/6.1-to-6.2.md b/doc/update/6.1-to-6.2.md
new file mode 100644
index 00000000000..747b4860796
--- /dev/null
+++ b/doc/update/6.1-to-6.2.md
@@ -0,0 +1,100 @@
+# From 6.1 to 6.2
+
+# You should update to 6.1 before installing 6.2 so all the necessary conversions are run.
+
+### 0. Backup
+
+It's useful to make a backup just in case things go south:
+(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
+```
+
+### 1. Stop server
+
+    sudo service gitlab stop
+
+### 2. Get latest code
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H git fetch
+sudo -u git -H git checkout 6-2-stable
+```
+
+### 3. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+sudo -u git -H git fetch
+sudo -u git -H git checkout v1.7.1
+```
+
+### 4. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL
+sudo -u git -H bundle install --without development test postgres --deployment
+
+#PostgreSQL
+sudo -u git -H bundle install --without development test mysql --deployment
+
+
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+sudo -u git -H bundle exec rake migrate_iids RAILS_ENV=production
+sudo -u git -H bundle exec rake assets:clean RAILS_ENV=production
+sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
+```
+
+### 5. Update config files
+
+* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/6-2-stable/config/gitlab.yml.example but with your settings.
+* Make `/home/git/gitlab/config/unicorn.rb` same as https://github.com/gitlabhq/gitlabhq/blob/6-2-stable/config/unicorn.rb.example but with your settings.
+* Copy rack attack middleware config
+```bash
+sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
+```
+* Uncomment `config.middleware.use Rack::Attack` in `/home/git/gitlab/config/application.rb`
+
+### 6. Update Init script
+
+```bash
+sudo rm /etc/init.d/gitlab
+sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/6-2-stable/lib/support/init.d/gitlab
+sudo chmod +x /etc/init.d/gitlab
+```
+
+### 7. Start application
+
+    sudo service gitlab start
+    sudo service nginx restart
+
+### 8. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+    sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+
+To make sure you didn't miss anything run a more thorough check with:
+
+    sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+
+If all items are green, then congratulations upgrade complete!
+
+## Things went south? Revert to previous version (6.1)
+
+### 1. Revert the code to the previous version
+Follow the [`upgrade guide from 6.0 to 6.1`](6.0-to-6.1.md), except for the database migration 
+(The backup is already migrated to the previous version)
+
+### 2. Restore from the backup:
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
+```
-- 
GitLab


From ea4fe45a46cc8bc653ae36eb32a95b4ac5cbb555 Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Tue, 1 Oct 2013 10:53:44 +0200
Subject: [PATCH 203/248] Also match if it is at the end or in the middle of a
 sentence.

---
 config/initializers/1_settings.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 0ce8074f951..1adb5c4e64d 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -69,7 +69,7 @@ rescue ArgumentError # no user configured
 end
 Settings.gitlab['signup_enabled'] ||= false
 Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
-Settings.gitlab['issue_closing_pattern'] = '^([Cc]loses|[Ff]ixes) #(\d+)' if Settings.gitlab['issue_closing_pattern'].nil?
+Settings.gitlab['issue_closing_pattern'] = '([Cc]loses|[Ff]ixes) #(\d+)' if Settings.gitlab['issue_closing_pattern'].nil?
 Settings.gitlab['default_projects_features'] ||= {}
 Settings.gitlab['webhook_timeout'] ||= 10   
 Settings.gitlab.default_projects_features['issues']         = true if Settings.gitlab.default_projects_features['issues'].nil?
-- 
GitLab


From d7dbbd655282db906d1e54de406494a37e75c548 Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Tue, 1 Oct 2013 11:43:53 +0200
Subject: [PATCH 204/248] Also update example.

---
 config/gitlab.yml.example | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 60a21f673f4..3490d42e6a9 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -56,9 +56,10 @@ production: &base
     # signup_enabled: true
 
     ## Automatic issue closing
-    # If a commit message matches this regular express, all issues referenced from the matched text will be closed
-    # if it's pushed to a project's default branch.
-    # issue_closing_pattern: ^([Cc]loses|[Ff]ixes) +#\d+
+    # If a commit message matches this regular express, all issues referenced from the matched text will be closed.
+    # This  happends when the commit is pushed or merged into the default branch of a project.
+    # When not specified the default issue_closing_pattern as specified below will be used.
+    # issue_closing_pattern: ([Cc]loses|[Ff]ixes) +#\d+
 
     ## Default project features settings
     default_projects_features:
-- 
GitLab


From 8cb811c61cdff1d4cdb8b13cf639a72e6fd61b8d Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Tue, 1 Oct 2013 13:52:57 +0200
Subject: [PATCH 205/248] Update user api documentation

---
 doc/api/users.md | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/doc/api/users.md b/doc/api/users.md
index 50c0f560d87..16479ea6e0d 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -43,7 +43,8 @@ GET /users
     "theme_id": 1,
     "color_scheme_id": 3,
     "is_admin": false,
-    "can_create_group": true
+    "can_create_group": true,
+    "can_create_project": true
   }
 ]
 ```
@@ -78,7 +79,8 @@ Parameters:
   "theme_id": 1,
   "color_scheme_id": 2,
   "is_admin": false,
-  "can_create_group": true
+  "can_create_group": true,
+  "can_create_project": true
 }
 ```
 
-- 
GitLab


From b765781d2fc47f58b51429b7b8b76f55c775d26b Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 1 Oct 2013 15:15:14 +0300
Subject: [PATCH 206/248] Use annotate from rubygems

---
 Gemfile      |  3 ++-
 Gemfile.lock | 13 ++++---------
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/Gemfile b/Gemfile
index b38c0615589..072a4f16cd2 100644
--- a/Gemfile
+++ b/Gemfile
@@ -148,10 +148,11 @@ group :assets do
 end
 
 group :development do
-  gem "annotate", git: "https://github.com/ctran/annotate_models.git"
+  gem "annotate", "~> 2.6.0.beta2"
   gem "letter_opener"
   gem 'quiet_assets', '~> 1.0.1'
   gem 'rack-mini-profiler'
+
   # Better errors handler
   gem 'better_errors'
   gem 'binding_of_caller'
diff --git a/Gemfile.lock b/Gemfile.lock
index 1bc13fffb68..64616395938 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,11 +1,3 @@
-GIT
-  remote: https://github.com/ctran/annotate_models.git
-  revision: 18a4e2eb77c8f3ef695b563e4a7ca45dfede819b
-  specs:
-    annotate (2.6.0.beta2)
-      activerecord (>= 2.3.0)
-      rake (>= 0.8.7)
-
 GEM
   remote: https://rubygems.org/
   specs:
@@ -39,6 +31,9 @@ GEM
     acts-as-taggable-on (2.4.1)
       rails (>= 3, < 5)
     addressable (2.3.4)
+    annotate (2.6.0.beta2)
+      activerecord (>= 2.3.0)
+      rake (>= 0.8.7)
     arel (3.0.2)
     asciidoctor (0.1.3)
     awesome_print (1.2.0)
@@ -558,7 +553,7 @@ PLATFORMS
 
 DEPENDENCIES
   acts-as-taggable-on
-  annotate!
+  annotate (~> 2.6.0.beta2)
   asciidoctor
   awesome_print
   better_errors
-- 
GitLab


From 2432015b034b62971b63e462b74bf9f9d9667574 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 1 Oct 2013 15:15:28 +0300
Subject: [PATCH 207/248] Annotate!

---
 app/assets/javascripts/api.js.coffee | 6 +++---
 app/models/group.rb                  | 2 +-
 app/models/merge_request.rb          | 1 +
 app/models/namespace.rb              | 2 +-
 app/models/note.rb                   | 1 +
 app/models/pivotaltracker_service.rb | 3 +++
 spec/models/group_spec.rb            | 2 +-
 spec/models/merge_request_spec.rb    | 1 +
 spec/models/namespace_spec.rb        | 2 +-
 spec/models/note_spec.rb             | 1 +
 10 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/app/assets/javascripts/api.js.coffee b/app/assets/javascripts/api.js.coffee
index db80e7b0f3c..a36d944cbcb 100644
--- a/app/assets/javascripts/api.js.coffee
+++ b/app/assets/javascripts/api.js.coffee
@@ -3,12 +3,12 @@
   user_path: "/api/:version/users/:id.json"
   notes_path: "/api/:version/projects/:id/notes.json"
 
-  # Get 20 (depends on api) recent notes 
+  # Get 20 (depends on api) recent notes
   # and sort the ascending from oldest to newest
   notes: (project_id, callback) ->
     url = Api.buildUrl(Api.notes_path)
     url = url.replace(':id', project_id)
-    
+
     $.ajax(
       url: url,
       data:
@@ -37,7 +37,7 @@
   # Only active users retrieved
   users: (query, callback) ->
     url = Api.buildUrl(Api.users_path)
-    
+
     $.ajax(
       url: url
       data:
diff --git a/app/models/group.rb b/app/models/group.rb
index 0cc3a3a0f41..d6272ca46f5 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -5,7 +5,7 @@
 #  id          :integer          not null, primary key
 #  name        :string(255)      not null
 #  path        :string(255)      not null
-#  owner_id    :integer          not null
+#  owner_id    :integer
 #  created_at  :datetime         not null
 #  updated_at  :datetime         not null
 #  type        :string(255)
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 7f367588b23..a26190015b2 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -18,6 +18,7 @@
 #  merge_status      :string(255)
 #  target_project_id :integer          not null
 #  iid               :integer
+#  description       :text
 #
 
 require Rails.root.join("app/models/commit")
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 6ac94c06604..fde06649c78 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -5,7 +5,7 @@
 #  id          :integer          not null, primary key
 #  name        :string(255)      not null
 #  path        :string(255)      not null
-#  owner_id    :integer          not null
+#  owner_id    :integer
 #  created_at  :datetime         not null
 #  updated_at  :datetime         not null
 #  type        :string(255)
diff --git a/app/models/note.rb b/app/models/note.rb
index e819a5516b5..7e7387abed6 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -14,6 +14,7 @@
 #  commit_id     :string(255)
 #  noteable_id   :integer
 #  st_diff       :text
+#  system        :boolean          default(FALSE), not null
 #
 
 require 'carrierwave/orm/activerecord'
diff --git a/app/models/pivotaltracker_service.rb b/app/models/pivotaltracker_service.rb
index f28e142da77..c5b1b9ab8d3 100644
--- a/app/models/pivotaltracker_service.rb
+++ b/app/models/pivotaltracker_service.rb
@@ -10,6 +10,9 @@
 #  created_at  :datetime         not null
 #  updated_at  :datetime         not null
 #  active      :boolean          default(FALSE), not null
+#  project_url :string(255)
+#  subdomain   :string(255)
+#  room        :string(255)
 #
 
 class PivotaltrackerService < Service
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index ce1aa05bcd7..4a08ad3bb15 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -5,7 +5,7 @@
 #  id          :integer          not null, primary key
 #  name        :string(255)      not null
 #  path        :string(255)      not null
-#  owner_id    :integer          not null
+#  owner_id    :integer
 #  created_at  :datetime         not null
 #  updated_at  :datetime         not null
 #  type        :string(255)
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 18c32d4fb74..703f46adba3 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -18,6 +18,7 @@
 #  merge_status      :string(255)
 #  target_project_id :integer          not null
 #  iid               :integer
+#  description       :text
 #
 
 require 'spec_helper'
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 0a0509bcd27..c38554e2f77 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -5,7 +5,7 @@
 #  id          :integer          not null, primary key
 #  name        :string(255)      not null
 #  path        :string(255)      not null
-#  owner_id    :integer          not null
+#  owner_id    :integer
 #  created_at  :datetime         not null
 #  updated_at  :datetime         not null
 #  type        :string(255)
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index ef143debcc1..42c405d8e50 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -14,6 +14,7 @@
 #  commit_id     :string(255)
 #  noteable_id   :integer
 #  st_diff       :text
+#  system        :boolean          default(FALSE), not null
 #
 
 require 'spec_helper'
-- 
GitLab


From 709b20eb6ed542a601f48529bfcc445c069682f7 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 1 Oct 2013 17:00:28 +0300
Subject: [PATCH 208/248] Update code to work with gitlab_git 3

---
 Gemfile                                      |  2 +-
 Gemfile.lock                                 |  4 ++--
 app/controllers/projects/blame_controller.rb |  2 +-
 app/controllers/projects/blob_controller.rb  |  2 +-
 app/controllers/projects/raw_controller.rb   |  4 ++--
 app/controllers/projects/refs_controller.rb  |  3 ++-
 app/controllers/projects/tree_controller.rb  |  2 ++
 app/helpers/blobs_helper.rb                  |  5 ++++
 app/helpers/tree_helper.rb                   | 10 ++++----
 app/models/repository.rb                     |  9 ++++++--
 app/models/tree.rb                           | 24 +++++++++++++-------
 app/views/projects/commits/_diffs.html.haml  |  8 +++----
 app/views/projects/tree/_tree.html.haml      |  2 +-
 config/initializers/5_backend.rb             |  3 ---
 lib/extracts_path.rb                         |  8 ++++---
 15 files changed, 54 insertions(+), 34 deletions(-)
 create mode 100644 app/helpers/blobs_helper.rb

diff --git a/Gemfile b/Gemfile
index 072a4f16cd2..50ce0c14570 100644
--- a/Gemfile
+++ b/Gemfile
@@ -23,7 +23,7 @@ gem 'omniauth-github'
 
 # Extracting information from a git repository
 # Provide access to Gitlab::Git library
-gem "gitlab_git", '2.3.1'
+gem "gitlab_git", "~> 3.0.0.beta1"
 
 # Ruby/Rack Git Smart-HTTP Server Handler
 gem 'gitlab-grack', '~> 1.0.1', require: 'grack'
diff --git a/Gemfile.lock b/Gemfile.lock
index 64616395938..f39aeb6ec2a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -177,7 +177,7 @@ GEM
     gitlab-pygments.rb (0.3.2)
       posix-spawn (~> 0.3.6)
       yajl-ruby (~> 1.1.0)
-    gitlab_git (2.3.1)
+    gitlab_git (3.0.0.beta1)
       activesupport (~> 3.2.13)
       github-linguist (~> 2.3.4)
       gitlab-grit (~> 2.6.0)
@@ -582,7 +582,7 @@ DEPENDENCIES
   gitlab-gollum-lib (~> 1.0.1)
   gitlab-grack (~> 1.0.1)
   gitlab-pygments.rb (~> 0.3.2)
-  gitlab_git (= 2.3.1)
+  gitlab_git (~> 3.0.0.beta1)
   gitlab_meta (= 6.0)
   gitlab_omniauth-ldap (= 1.0.3)
   gon
diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb
index e58b4507202..f22c6497cbf 100644
--- a/app/controllers/projects/blame_controller.rb
+++ b/app/controllers/projects/blame_controller.rb
@@ -8,7 +8,7 @@ class Projects::BlameController < Projects::ApplicationController
   before_filter :require_non_empty_project
 
   def show
-    @blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path)
+    @blob = Gitlab::Git::Blob.find(@repository, @commit.id, @path)
     @blame = Gitlab::Git::Blame.new(project.repository, @commit.id, @path)
   end
 end
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index b1329c01ce7..33dbc869996 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -8,6 +8,6 @@ class Projects::BlobController < Projects::ApplicationController
   before_filter :require_non_empty_project
 
   def show
-    @blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path)
+    @blob = Gitlab::Git::Blob.find(@repository, @commit.id, @path)
   end
 end
diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb
index 0c23d411f4c..8633b225b64 100644
--- a/app/controllers/projects/raw_controller.rb
+++ b/app/controllers/projects/raw_controller.rb
@@ -8,9 +8,9 @@ class Projects::RawController < Projects::ApplicationController
   before_filter :require_non_empty_project
 
   def show
-    @blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path)
+    @blob = Gitlab::Git::Blob.find(@repository, @commit.id, @path)
 
-    if @blob.exists?
+    if @blob
       type = if @blob.mime_type =~ /html|javascript/
                'text/plain; charset=utf-8'
              else
diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb
index e5c090e1f4d..16621c0371e 100644
--- a/app/controllers/projects/refs_controller.rb
+++ b/app/controllers/projects/refs_controller.rb
@@ -24,13 +24,14 @@ class Projects::RefsController < Projects::ApplicationController
       format.js do
         @ref = params[:ref]
         define_tree_vars
+        tree
         render "tree"
       end
     end
   end
 
   def logs_tree
-    contents = @tree.entries
+    contents = tree.entries
     @logs = contents.map do |content|
       file = params[:path] ? File.join(params[:path], content.name) : content.name
       last_commit = @repo.commits(@commit.id, file, 1).last
diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb
index 5d543f35665..1150efbea9d 100644
--- a/app/controllers/projects/tree_controller.rb
+++ b/app/controllers/projects/tree_controller.rb
@@ -8,6 +8,8 @@ class Projects::TreeController < Projects::ApplicationController
   before_filter :require_non_empty_project
 
   def show
+    return not_found! if tree.entries.empty?
+
     respond_to do |format|
       format.html
       # Disable cache so browser history works
diff --git a/app/helpers/blobs_helper.rb b/app/helpers/blobs_helper.rb
new file mode 100644
index 00000000000..26605d81026
--- /dev/null
+++ b/app/helpers/blobs_helper.rb
@@ -0,0 +1,5 @@
+module BlobsHelper
+  def find_blob(repository, sha, path)
+    Gitlab::Git::Blob.find(repository, sha, path)
+  end
+end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 73d36d0801c..2dbc1cffb16 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -67,9 +67,9 @@ module TreeHelper
   end
 
   def tree_breadcrumbs(tree, max_links = 2)
-    if tree.path
+    if @path.present?
       part_path = ""
-      parts = tree.path.split("\/")
+      parts = @path.split("\/")
 
       yield('..', nil) if parts.count > max_links
 
@@ -78,14 +78,14 @@ module TreeHelper
         part_path = part if part_path.empty?
 
         next unless parts.last(2).include?(part) if parts.count > max_links
-        yield(part, tree_join(tree.ref, part_path))
+        yield(part, tree_join(@ref, part_path))
       end
     end
   end
 
   def up_dir_path tree
-    file = File.join(tree.path, "..")
-    tree_join(tree.ref, file)
+    file = File.join(@path, "..")
+    tree_join(@ref, file)
   end
 
   def leave_edit_message
diff --git a/app/models/repository.rb b/app/models/repository.rb
index aeec48ee5cc..734d060095e 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -1,14 +1,19 @@
 class Repository
   include Gitlab::ShellAdapter
 
-  attr_accessor :raw_repository
+  attr_accessor :raw_repository, :path_with_namespace
 
   def initialize(path_with_namespace, default_branch)
-    @raw_repository = Gitlab::Git::Repository.new(path_with_namespace, default_branch)
+    @path_with_namespace = path_with_namespace
+    @raw_repository = Gitlab::Git::Repository.new(path_to_repo)
   rescue Gitlab::Git::Repository::NoRepository
     nil
   end
 
+  def path_to_repo
+    @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, path_with_namespace + ".git")
+  end
+
   def exists?
     raw_repository
   end
diff --git a/app/models/tree.rb b/app/models/tree.rb
index 042050527c1..5fbad19b468 100644
--- a/app/models/tree.rb
+++ b/app/models/tree.rb
@@ -1,17 +1,25 @@
 class Tree
-  attr_accessor :raw
+  attr_accessor :entries, :readme
 
-  def initialize(repository, sha, ref = nil, path = nil)
-    @raw = Gitlab::Git::Tree.new(repository, sha, ref, path)
+  def initialize(repository, sha, path = '/')
+    path = '/' if path.blank?
+    git_repo = repository.raw_repository
+    @entries = Gitlab::Git::Tree.where(git_repo, sha, path)
+
+    if readme_tree = @entries.find(&:readme?)
+      @readme = Gitlab::Git::Blob.find(git_repo, sha, readme_tree.name)
+    end
   end
 
-  def method_missing(m, *args, &block)
-    @raw.send(m, *args, &block)
+  def trees
+    @entries.select(&:dir?)
   end
 
-  def respond_to?(method)
-    return true if @raw.respond_to?(method)
+  def blobs
+    @entries.select(&:file?)
+  end
 
-    super
+  def submodules
+    @entries.select(&:submodule?)
   end
 end
diff --git a/app/views/projects/commits/_diffs.html.haml b/app/views/projects/commits/_diffs.html.haml
index c51f1b6eff5..f60c4661100 100644
--- a/app/views/projects/commits/_diffs.html.haml
+++ b/app/views/projects/commits/_diffs.html.haml
@@ -37,9 +37,9 @@
   - unless @suppress_diff
     - diffs.each_with_index do |diff, i|
       - next if diff.diff.empty?
-      - file = Gitlab::Git::Blob.new(project.repository, @commit.id, @ref, diff.new_path)
-      - file = Gitlab::Git::Blob.new(project.repository, @commit.parent_id, @ref, diff.old_path) unless file.exists?
-      - next unless file.exists?
+      - file = find_blob(project.repository, @commit.id, diff.new_path)
+      - file = find_blob(project.repository, @commit.parent_id, diff.old_path) unless file
+      - next unless file
       .file{id: "diff-#{i}"}
         .header
           - if diff.deleted_file
@@ -64,7 +64,7 @@
           - if file.text?
             = render "projects/commits/text_file", diff: diff, index: i
           - elsif file.image?
-            - old_file = Gitlab::Git::Blob.new(project.repository, @commit.parent_id, @ref, diff.old_path) if @commit.parent_id
+            - old_file = find_blob(project.repository, @commit.parent_id, diff.old_path) if @commit.parent_id
             = render "projects/commits/image", diff: diff, old_file: old_file, file: file, index: i
           - else
             %p.nothing_here_message No preview for this file type
diff --git a/app/views/projects/tree/_tree.html.haml b/app/views/projects/tree/_tree.html.haml
index ae5f30c0004..eadfd33bd3c 100644
--- a/app/views/projects/tree/_tree.html.haml
+++ b/app/views/projects/tree/_tree.html.haml
@@ -28,7 +28,7 @@
             = truncate(@commit.title, length: 50)
         %th= link_to "history", project_commits_path(@project, @id), class: "pull-right"
 
-    - if tree.up_dir?
+    - if @path.present?
       %tr.tree-item
         %td.tree-item-file-name
           = image_tag "file_empty.png", size: '16x16'
diff --git a/config/initializers/5_backend.rb b/config/initializers/5_backend.rb
index e60d9559c94..7c2e7f39000 100644
--- a/config/initializers/5_backend.rb
+++ b/config/initializers/5_backend.rb
@@ -6,6 +6,3 @@ require Rails.root.join("lib", "gitlab", "backend", "shell")
 
 # GitLab shell adapter
 require Rails.root.join("lib", "gitlab", "backend", "shell_adapter")
-
-# Gitlab Git repos path
-Gitlab::Git::Repository.repos_path = Gitlab.config.gitlab_shell.repos_path
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index 53bc079296a..5f28d624402 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -86,7 +86,6 @@ module ExtractsPath
   # - @ref    - A string representing the ref (e.g., the branch, tag, or commit SHA)
   # - @path   - A string representing the filesystem path
   # - @commit - A Commit representing the commit from the given ref
-  # - @tree   - A Tree representing the tree at the given ref/path
   #
   # If the :id parameter appears to be requesting a specific response format,
   # that will be handled as well.
@@ -107,15 +106,18 @@ module ExtractsPath
     else
       @commit = @repo.commit(@options[:extended_sha1])
     end
-    @tree = Tree.new(@repo, @commit.id, @ref, @path)
+
     @hex_path = Digest::SHA1.hexdigest(@path)
     @logs_path = logs_file_project_ref_path(@project, @ref, @path)
 
-    raise InvalidPathError unless @tree.exists?
   rescue RuntimeError, NoMethodError, InvalidPathError
     not_found!
   end
 
+  def tree
+    @tree ||= Tree.new(@repo, @commit.id, @path)
+  end
+
   private
 
   def get_id
-- 
GitLab


From 9cc498a6e8e4c62f266dbf977a28b7c27512588a Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 1 Oct 2013 17:08:40 +0300
Subject: [PATCH 209/248] Fix edit file

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

diff --git a/app/controllers/projects/edit_tree_controller.rb b/app/controllers/projects/edit_tree_controller.rb
index 3b945fc7126..edea80a5ccc 100644
--- a/app/controllers/projects/edit_tree_controller.rb
+++ b/app/controllers/projects/edit_tree_controller.rb
@@ -32,9 +32,9 @@ class Projects::EditTreeController < Projects::ApplicationController
   private
 
   def edit_requirements
-    @blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path)
+    @blob = Gitlab::Git::Blob.find(@repository, @commit.id, @path)
 
-    unless @blob.exists? && @blob.text?
+    unless @blob
       redirect_to project_blob_path(@project, @id), notice: "You can only edit text files"
     end
 
-- 
GitLab


From d322bfae81d462021ce60167264309c521216aed Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 1 Oct 2013 18:26:55 +0300
Subject: [PATCH 210/248] Fix blob and repo stuff after gitlab_git v3

---
 app/assets/stylesheets/gitlab_bootstrap/files.scss |  6 ++++++
 app/controllers/projects/blob_controller.rb        |  2 ++
 app/models/repository.rb                           |  2 +-
 app/views/projects/blob/_download.html.haml        | 11 +++++------
 lib/api/repositories.rb                            |  6 +++---
 lib/extracts_path.rb                               |  2 ++
 6 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/app/assets/stylesheets/gitlab_bootstrap/files.scss b/app/assets/stylesheets/gitlab_bootstrap/files.scss
index 8ba8c93e3d6..a286e530cd6 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/files.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/files.scss
@@ -69,6 +69,12 @@
 
     }
 
+    &.blob-no-preview {
+      background: #eee;
+      text-shadow: 0 1px 2px #FFF;
+      padding: 100px 0;
+    }
+
     /**
      *  Blame file
      */
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 33dbc869996..878f25c7c03 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -9,5 +9,7 @@ class Projects::BlobController < Projects::ApplicationController
 
   def show
     @blob = Gitlab::Git::Blob.find(@repository, @commit.id, @path)
+
+    not_found! unless @blob
   end
 end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 734d060095e..145bd51ffd3 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -5,7 +5,7 @@ class Repository
 
   def initialize(path_with_namespace, default_branch)
     @path_with_namespace = path_with_namespace
-    @raw_repository = Gitlab::Git::Repository.new(path_to_repo)
+    @raw_repository = Gitlab::Git::Repository.new(path_to_repo) if path_with_namespace
   rescue Gitlab::Git::Repository::NoRepository
     nil
   end
diff --git a/app/views/projects/blob/_download.html.haml b/app/views/projects/blob/_download.html.haml
index f3da1a2a219..ff317f90209 100644
--- a/app/views/projects/blob/_download.html.haml
+++ b/app/views/projects/blob/_download.html.haml
@@ -1,8 +1,7 @@
-.file-content.blob_file
+.file-content.blob_file.blob-no-preview
   %center
     = link_to project_raw_path(@project, @id) do
-      %div.padded
-        %h4
-          %i.icon-download-alt
-          %br
-          Download (#{number_to_human_size blob.size})
+      %h1.light
+        %i.icon-download-alt
+      %h4
+        Download (#{number_to_human_size blob.size})
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index c2b229b0172..1a911eae2bb 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -139,7 +139,7 @@ module API
         path = params[:path] || nil
 
         commit = user_project.repository.commit(ref)
-        tree = Tree.new(user_project.repository, commit.id, ref, path)
+        tree = Tree.new(user_project.repository, commit.id, path)
 
         trees = []
 
@@ -168,8 +168,8 @@ module API
         commit = repo.commit(ref)
         not_found! "Commit" unless commit
 
-        blob = Gitlab::Git::Blob.new(repo, commit.id, ref, params[:filepath])
-        not_found! "File" unless blob.exists?
+        blob = Gitlab::Git::Blob.find(repo, commit.id, params[:filepath])
+        not_found! "File" unless blob
 
         env['api.format'] = :txt
 
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index 5f28d624402..6e7872dcd03 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -107,6 +107,8 @@ module ExtractsPath
       @commit = @repo.commit(@options[:extended_sha1])
     end
 
+    raise InvalidPathError unless @commit
+
     @hex_path = Digest::SHA1.hexdigest(@path)
     @logs_path = logs_file_project_ref_path(@project, @ref, @path)
 
-- 
GitLab


From bfcc5b35d067c336727c343f4e3a3ee9dfe62a28 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 1 Oct 2013 20:34:41 +0300
Subject: [PATCH 211/248] Refactor blob finding

---
 app/controllers/projects/blame_controller.rb     | 2 +-
 app/controllers/projects/blob_controller.rb      | 2 +-
 app/controllers/projects/edit_tree_controller.rb | 4 ++--
 app/controllers/projects/raw_controller.rb       | 2 +-
 app/helpers/blobs_helper.rb                      | 5 -----
 app/models/repository.rb                         | 4 ++++
 app/views/projects/commits/_diffs.html.haml      | 6 +++---
 7 files changed, 12 insertions(+), 13 deletions(-)
 delete mode 100644 app/helpers/blobs_helper.rb

diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb
index f22c6497cbf..a3c41301676 100644
--- a/app/controllers/projects/blame_controller.rb
+++ b/app/controllers/projects/blame_controller.rb
@@ -8,7 +8,7 @@ class Projects::BlameController < Projects::ApplicationController
   before_filter :require_non_empty_project
 
   def show
-    @blob = Gitlab::Git::Blob.find(@repository, @commit.id, @path)
+    @blob = @repository.blob_at(@commit.id, @path)
     @blame = Gitlab::Git::Blame.new(project.repository, @commit.id, @path)
   end
 end
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 878f25c7c03..ba466251b29 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -8,7 +8,7 @@ class Projects::BlobController < Projects::ApplicationController
   before_filter :require_non_empty_project
 
   def show
-    @blob = Gitlab::Git::Blob.find(@repository, @commit.id, @path)
+    @blob = @repository.blob_at(@commit.id, @path)
 
     not_found! unless @blob
   end
diff --git a/app/controllers/projects/edit_tree_controller.rb b/app/controllers/projects/edit_tree_controller.rb
index edea80a5ccc..5d05c585ecc 100644
--- a/app/controllers/projects/edit_tree_controller.rb
+++ b/app/controllers/projects/edit_tree_controller.rb
@@ -10,7 +10,7 @@ class Projects::EditTreeController < Projects::ApplicationController
   before_filter :edit_requirements, only: [:show, :update]
 
   def show
-    @last_commit = Gitlab::Git::Commit.last_for_path(@project.repository, @ref, @path).sha
+    @last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha
   end
 
   def update
@@ -32,7 +32,7 @@ class Projects::EditTreeController < Projects::ApplicationController
   private
 
   def edit_requirements
-    @blob = Gitlab::Git::Blob.find(@repository, @commit.id, @path)
+    @blob = @repository.blob_at(@commit.id, @path)
 
     unless @blob
       redirect_to project_blob_path(@project, @id), notice: "You can only edit text files"
diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb
index 8633b225b64..18ace028b0c 100644
--- a/app/controllers/projects/raw_controller.rb
+++ b/app/controllers/projects/raw_controller.rb
@@ -8,7 +8,7 @@ class Projects::RawController < Projects::ApplicationController
   before_filter :require_non_empty_project
 
   def show
-    @blob = Gitlab::Git::Blob.find(@repository, @commit.id, @path)
+    @blob = @repository.blob_at(@commit.id, @path)
 
     if @blob
       type = if @blob.mime_type =~ /html|javascript/
diff --git a/app/helpers/blobs_helper.rb b/app/helpers/blobs_helper.rb
deleted file mode 100644
index 26605d81026..00000000000
--- a/app/helpers/blobs_helper.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-module BlobsHelper
-  def find_blob(repository, sha, path)
-    Gitlab::Git::Blob.find(repository, sha, path)
-  end
-end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 145bd51ffd3..97b4330092a 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -155,4 +155,8 @@ class Repository
 
     super
   end
+
+  def blob_at(sha, path)
+    Gitlab::Git::Blob.find(self, sha, path)
+  end
 end
diff --git a/app/views/projects/commits/_diffs.html.haml b/app/views/projects/commits/_diffs.html.haml
index f60c4661100..2e61b9ece19 100644
--- a/app/views/projects/commits/_diffs.html.haml
+++ b/app/views/projects/commits/_diffs.html.haml
@@ -37,8 +37,8 @@
   - unless @suppress_diff
     - diffs.each_with_index do |diff, i|
       - next if diff.diff.empty?
-      - file = find_blob(project.repository, @commit.id, diff.new_path)
-      - file = find_blob(project.repository, @commit.parent_id, diff.old_path) unless file
+      - file = project.repository.blob_at(@commit.id, diff.new_path)
+      - file = project.repository.blob_at(@commit.parent_id, diff.old_path) unless file
       - next unless file
       .file{id: "diff-#{i}"}
         .header
@@ -64,7 +64,7 @@
           - if file.text?
             = render "projects/commits/text_file", diff: diff, index: i
           - elsif file.image?
-            - old_file = find_blob(project.repository, @commit.parent_id, diff.old_path) if @commit.parent_id
+            - old_file = project.repository.blob_at(@commit.parent_id, diff.old_path) if @commit.parent_id
             = render "projects/commits/image", diff: diff, old_file: old_file, file: file, index: i
           - else
             %p.nothing_here_message No preview for this file type
-- 
GitLab


From f2ce678129d4b6017524500402edf2ba4852ea28 Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Tue, 1 Oct 2013 23:13:09 +0200
Subject: [PATCH 212/248] Update project api docs.

---
 doc/api/projects.md | 184 +++++++++++++++++++++++++++++++-------------
 1 file changed, 132 insertions(+), 52 deletions(-)

diff --git a/doc/api/projects.md b/doc/api/projects.md
index 5150331e7d7..d247c07ece4 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -11,51 +11,72 @@ GET /projects
 ```json
 [
   {
-    "id": 3,
-    "name": "rails",
+    "id": 4,
     "description": null,
     "default_branch": "master",
+    "public": false,
+    "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git",
+    "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git",
+    "web_url": "http://example.com/diaspora/diaspora-client",
     "owner": {
-      "id": 1,
-      "username": "john_smith",
-      "email": "john@example.com",
-      "name": "John Smith",
-      "blocked": false,
-      "created_at": "2012-05-23T08:00:58Z"
+      "id": 3,
+      "name": "Diaspora",
+      "created_at": "2013-09-30T13: 46: 02Z"
     },
-    "public": true,
-    "path": "rails",
-    "path_with_namespace": "rails/rails",
-    "issues_enabled": false,
-    "merge_requests_enabled": false,
-    "wall_enabled": true,
+    "name": "Diaspora Client",
+    "name_with_namespace": "Diaspora / Diaspora Client",
+    "path": "diaspora-client",
+    "path_with_namespace": "diaspora/diaspora-client",
+    "issues_enabled": true,
+    "merge_requests_enabled": true,
+    "wall_enabled": false,
     "wiki_enabled": true,
-    "created_at": "2012-05-23T08:05:02Z",
-    "last_activity_at": "2012-05-23T08:05:02Z"
+    "snippets_enabled": false,
+    "created_at": "2013-09-30T13: 46: 02Z",
+    "last_activity_at": "2013-09-30T13: 46: 02Z",
+    "namespace": {
+      "created_at": "2013-09-30T13: 46: 02Z",
+      "description": "",
+      "id": 3,
+      "name": "Diaspora",
+      "owner_id": 1,
+      "path": "diaspora",
+      "updated_at": "2013-09-30T13: 46: 02Z"
+    }
   },
   {
-    "id": 5,
-    "name": "gitlab",
+    "id": 6,
     "description": null,
-    "default_branch": "api",
-    "owner": {
-      "id": 1,
-      "username": "john_smith",
-      "email": "john@example.com",
-      "name": "John Smith",
-      "blocked": false,
-      "created_at": "2012-05-23T08:00:58Z"
+    "default_branch": "master",
+    "public": false,
+    "ssh_url_to_repo": "git@example.com:brightbox/puppet.git",
+    "http_url_to_repo": "http://example.com/brightbox/puppet.git",
+    "web_url": "http://example.com/brightbox/puppet",
+    "owner":  {
+      "id": 4,
+      "name": "Brightbox",
+      "created_at": "2013-09-30T13:46:02Z"
     },
-    "public": true,
-    "path": "gitlab",
-    "path_with_namespace": "randx/gitlab",
+    "name": "Puppet",
+    "name_with_namespace": "Brightbox / Puppet",
+    "path": "puppet",
+    "path_with_namespace": "brightbox/puppet",
     "issues_enabled": true,
     "merge_requests_enabled": true,
-    "wall_enabled": true,
+    "wall_enabled": false,
     "wiki_enabled": true,
-    "snippets_enabled": true,
-    "created_at": "2012-05-30T12:49:20Z",
-    "last_activity_at": "2012-05-23T08:05:02Z"
+    "snippets_enabled": false,
+    "created_at": "2013-09-30T13:46:02Z",
+    "last_activity_at": "2013-09-30T13:46:02Z",
+    "namespace":  {
+      "created_at": "2013-09-30T13:46:02Z",
+      "description": "",
+      "id": 4,
+      "name": "Brightbox",
+      "owner_id": 1,
+      "path": "brightbox",
+      "updated_at": "2013-09-30T13:46:02Z"
+    }
   }
 ]
 ```
@@ -76,29 +97,38 @@ Parameters:
 
 ```json
 {
-  "id": 5,
-  "name": "gitlab",
-  "name_with_namespace": "GitLab / gitlabhq",
+  "id": 3,
   "description": null,
-  "default_branch": "api",
+  "default_branch": "master",
+  "public": false,
+  "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git",
+  "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
+  "web_url": "http://example.com/diaspora/diaspora-project-site",
   "owner": {
-    "id": 1,
-    "username": "john_smith",
-    "email": "john@example.com",
-    "name": "John Smith",
-    "blocked": false,
-    "created_at": "2012-05-23T08:00:58Z"
+    "id": 3,
+    "name": "Diaspora",
+    "created_at": "2013-09-30T13: 46: 02Z"
   },
-  "public": true,
-  "path": "gitlab",
-  "path_with_namespace": "randx/gitlab",
+  "name": "Diaspora Project Site",
+  "name_with_namespace": "Diaspora / Diaspora Project Site",
+  "path": "diaspora-project-site",
+  "path_with_namespace": "diaspora/diaspora-project-site",
   "issues_enabled": true,
   "merge_requests_enabled": true,
-  "wall_enabled": true,
+  "wall_enabled": false,
   "wiki_enabled": true,
-  "snippets_enabled": true,
-  "created_at": "2012-05-30T12:49:20Z",
-  "last_activity_at": "2012-05-23T08:05:02Z"
+  "snippets_enabled": false,
+  "created_at": "2013-09-30T13: 46: 02Z",
+  "last_activity_at": "2013-09-30T13: 46: 02Z",
+  "namespace": {
+    "created_at": "2013-09-30T13: 46: 02Z",
+    "description": "",
+    "id": 3,
+    "name": "Diaspora",
+    "owner_id": 1,
+    "path": "diaspora",
+    "updated_at": "2013-09-30T13: 46: 02Z"
+  }
 }
 ```
 
@@ -193,13 +223,14 @@ Parameters:
 
 **Project access levels**
 
-The project access levels are defined in the `user_project.rb` class. Currently, these levels are recognized:
+The project access levels are defined in the `Gitlab::Access` module. Currently, these levels are recognized:
 
 ```
   GUEST     = 10
   REPORTER  = 20
   DEVELOPER = 30
   MASTER    = 40
+  OWNER     = 50
 ```
 
 
@@ -261,7 +292,7 @@ Parameters:
   "username": "john_smith",
   "email": "john@example.com",
   "name": "John Smith",
-  "blocked": false,
+  "state": "active",
   "created_at": "2012-05-23T08:00:58Z",
   "access_level": 40
 }
@@ -417,6 +448,55 @@ Parameters:
 
 + `id` (required) - The ID of the project
 
+```json
+[
+  {
+    "name":"async",
+    "commit": {
+      "id":"a2b702edecdf41f07b42653eb1abe30ce98b9fca",
+      "parents": [{
+        "id":"3f94fc7c85061973edc9906ae170cc269b07ca55"
+      }],
+      "tree": "c68537c6534a02cc2b176ca1549f4ffa190b58ee",
+      "message":"give caolan his credit where it's due (up top)",
+      "author": {
+        "name":"Jeremy Ashkenas",
+        "email":"jashkenas@example.com"
+      },
+      "committer": {
+        "name":"Jeremy Ashkenas",
+        "email":"jashkenas@example.com"
+      },
+      "authored_date":"2010-12-08T21:28:50+00:00",
+      "committed_date":"2010-12-08T21:28:50+00:00"
+    },
+    "protected":false
+  },
+  {
+    "name": "gh-pages",
+    "commit": {
+      "id": "101c10a60019fe870d21868835f65c25d64968fc",
+      "parents": [{
+        "id": "9c15d2e26945a665131af5d7b6d30a06ba338aaa"
+      }],
+      "tree": "fb5cc9d45da3014b17a876ad539976a0fb9b352a",
+      "message": "Underscore.js 1.5.2",
+      "author": {
+        "name": "Jeremy Ashkenas",
+        "email": "jashkenas@example.com"
+      },
+      "committer": {
+        "name": "Jeremy Ashkenas",
+        "email": "jashkenas@example.com"
+      },
+      "authored_date": "2013-09-07T12: 58: 21+00: 00",
+      "committed_date": "2013-09-07T12: 58: 21+00: 00"
+    },
+    "protected": false
+  }
+]
+
+```
 
 ### List single branch
 
-- 
GitLab


From 860ec232d3dfbf46616c1a876b725f36a15dbd2b Mon Sep 17 00:00:00 2001
From: Jacob Vosmaer <contact@jacobvosmaer.nl>
Date: Wed, 2 Oct 2013 08:05:32 +0200
Subject: [PATCH 213/248] Streamline MySQL setup in installation.md

---
 config/database.yml.mysql   | 2 +-
 doc/install/installation.md | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/config/database.yml.mysql b/config/database.yml.mysql
index a3eff1a74f8..e7a9227e41e 100644
--- a/config/database.yml.mysql
+++ b/config/database.yml.mysql
@@ -7,7 +7,7 @@ production:
   reconnect: false
   database: gitlabhq_production
   pool: 10
-  username: root
+  username: gitlab
   password: "secure password"
   # host: localhost
   # socket: /tmp/mysql.sock
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 03ea5fbb28f..91bf7c265a5 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -224,7 +224,6 @@ Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup.
     # Make sure to update username/password in config/database.yml.
     # You only need to adapt the production settings (first part).
     # If you followed the database guide then please do as follows:
-    # Change 'root' to 'gitlab'
     # Change 'secure password' with the value you have given to $password
     # You can keep the double quotes around the password
     sudo -u git -H editor config/database.yml
-- 
GitLab


From 8ebc54665f44220941729369cae7633faccc8c4e Mon Sep 17 00:00:00 2001
From: Jacob Vosmaer <contact@jacobvosmaer.nl>
Date: Wed, 2 Oct 2013 08:05:52 +0200
Subject: [PATCH 214/248] Use peer-based authentication for PostgreSQL

---
 config/database.yml.postgresql |  4 ++--
 doc/install/databases.md       |  2 +-
 doc/install/installation.md    | 11 ++++++-----
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/config/database.yml.postgresql b/config/database.yml.postgresql
index 4b74f3348f8..66960551cfd 100644
--- a/config/database.yml.postgresql
+++ b/config/database.yml.postgresql
@@ -6,8 +6,8 @@ production:
   encoding: unicode
   database: gitlabhq_production
   pool: 10
-  username: git
-  password:
+  # username: git
+  # password:
   # host: localhost
   # port: 5432 
   # socket: /tmp/postgresql.sock
diff --git a/doc/install/databases.md b/doc/install/databases.md
index 6477e1c967c..be7bc0aad2e 100644
--- a/doc/install/databases.md
+++ b/doc/install/databases.md
@@ -58,7 +58,7 @@ GitLab supports the following databases:
     sudo -u postgres psql -d template1
 
     # Create a user for GitLab. (change $password to a real password)
-    template1=# CREATE USER git WITH PASSWORD '$password';
+    template1=# CREATE USER git;
 
     # Create the GitLab production database & grant all privileges on database
     template1=# CREATE DATABASE gitlabhq_production OWNER git;
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 91bf7c265a5..933799776bd 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -216,17 +216,18 @@ Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup.
     # Mysql
     sudo -u git cp config/database.yml.mysql config/database.yml
 
-    or
-
-    # PostgreSQL
-    sudo -u git cp config/database.yml.postgresql config/database.yml
-
     # Make sure to update username/password in config/database.yml.
     # You only need to adapt the production settings (first part).
     # If you followed the database guide then please do as follows:
     # Change 'secure password' with the value you have given to $password
     # You can keep the double quotes around the password
     sudo -u git -H editor config/database.yml
+
+    or
+
+    # PostgreSQL
+    sudo -u git cp config/database.yml.postgresql config/database.yml
+
     
     # Make config/database.yml readable to git only
     sudo -u git -H chmod o-rwx config/database.yml
-- 
GitLab


From 19a2475879e3cd3a8331cfcb271b8b5335e5d8cc Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Wed, 2 Oct 2013 08:23:27 +0200
Subject: [PATCH 215/248] Correct spelling mistake.

---
 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 3490d42e6a9..ebbcf760c6c 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -56,7 +56,7 @@ production: &base
     # signup_enabled: true
 
     ## Automatic issue closing
-    # If a commit message matches this regular express, all issues referenced from the matched text will be closed.
+    # If a commit message matches this regular expression, all issues referenced from the matched text will be closed.
     # This  happends when the commit is pushed or merged into the default branch of a project.
     # When not specified the default issue_closing_pattern as specified below will be used.
     # issue_closing_pattern: ([Cc]loses|[Ff]ixes) +#\d+
-- 
GitLab


From 96779404eebf3a0dca794c03d1d02ac3e4b8f1a3 Mon Sep 17 00:00:00 2001
From: Jacob Vosmaer <contact@jacobvosmaer.nl>
Date: Wed, 2 Oct 2013 09:29:40 +0200
Subject: [PATCH 216/248] Add -H to sudo commands in 4.1-to-4.2.md

---
 doc/update/4.1-to-4.2.md | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/doc/update/4.1-to-4.2.md b/doc/update/4.1-to-4.2.md
index 536f22415e2..3aaf17b7727 100644
--- a/doc/update/4.1-to-4.2.md
+++ b/doc/update/4.1-to-4.2.md
@@ -12,15 +12,15 @@
 cd /home/gitlab/gitlab/
 
 # Get latest code
-sudo -u gitlab git fetch
+sudo -u gitlab -H git fetch
 
-sudo -u gitlab git checkout 4-2-stable
+sudo -u gitlab -H git checkout 4-2-stable
 
 # Install libs
-sudo -u gitlab bundle install --without development test postgres --deployment
+sudo -u gitlab -H bundle install --without development test postgres --deployment
 
 # update db
-sudo -u gitlab bundle exec rake db:migrate RAILS_ENV=production
+sudo -u gitlab -H bundle exec rake db:migrate RAILS_ENV=production
 
 ```
 
-- 
GitLab


From af25417cd4f2e4d6cb6296c287117ed140f2addf Mon Sep 17 00:00:00 2001
From: Jacob Vosmaer <contact@jacobvosmaer.nl>
Date: Wed, 2 Oct 2013 10:28:01 +0200
Subject: [PATCH 217/248] Use mkdir -p in 4.2-to-5.0.md update guide

---
 doc/update/4.2-to-5.0.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/doc/update/4.2-to-5.0.md b/doc/update/4.2-to-5.0.md
index 053a50ebc88..64b89ee93cf 100644
--- a/doc/update/4.2-to-5.0.md
+++ b/doc/update/4.2-to-5.0.md
@@ -85,7 +85,7 @@ sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
 sudo -u git -H bundle exec rake gitlab:shell:setup RAILS_ENV=production
 sudo -u git -H bundle exec rake gitlab:shell:build_missing_projects RAILS_ENV=production
 
-sudo -u git -H mkdir /home/git/gitlab-satellites
+sudo -u git -H mkdir -p /home/git/gitlab-satellites
 sudo -u git -H bundle exec rake gitlab:satellites:create RAILS_ENV=production
 
 # migrate wiki to git
@@ -101,7 +101,7 @@ sudo chown -R git /home/git/gitlab/log/
 sudo chown -R git /home/git/gitlab/tmp/
 sudo chmod -R u+rwX  /home/git/gitlab/log/
 sudo chmod -R u+rwX  /home/git/gitlab/tmp/
-sudo -u git -H mkdir /home/git/gitlab/tmp/pids/
+sudo -u git -H mkdir -p /home/git/gitlab/tmp/pids/
 sudo chmod -R u+rwX  /home/git/gitlab/tmp/pids
 
 ```
-- 
GitLab


From 3d35f871e87c49c733a2b941677ec5c248b6ae88 Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Wed, 2 Oct 2013 11:04:51 +0200
Subject: [PATCH 218/248] Update snippets and merge request api documentation

---
 doc/api/merge_requests.md   | 33 ++++++++++++++-------------------
 doc/api/project_snippets.md |  2 +-
 2 files changed, 15 insertions(+), 20 deletions(-)

diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 111c52112eb..e69d4bc99b9 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -19,14 +19,13 @@ Parameters:
         "source_branch":"test1",
         "project_id":3,
         "title":"test1",
-        "closed":true,
-        "merged":false,
+        "state":"opened",
         "author":{
             "id":1,
             "username": "admin",
             "email":"admin@local.host",
             "name":"Administrator",
-            "blocked":false,
+            "state":"active",
             "created_at":"2012-04-29T08:46:00Z"
         },
         "assignee":{
@@ -34,7 +33,7 @@ Parameters:
             "username": "admin",
             "email":"admin@local.host",
             "name":"Administrator",
-            "blocked":false,
+            "state":"active",
             "created_at":"2012-04-29T08:46:00Z"
         }
     }
@@ -62,14 +61,13 @@ Parameters:
     "source_branch":"test1",
     "project_id":3,
     "title":"test1",
-    "closed":true,
-    "merged":false,
+    "state":"merged",
     "author":{
         "id":1,
         "username": "admin",
         "email":"admin@local.host",
         "name":"Administrator",
-        "blocked":false,
+        "state":"active",
         "created_at":"2012-04-29T08:46:00Z"
     },
     "assignee":{
@@ -77,7 +75,7 @@ Parameters:
         "username": "admin",
         "email":"admin@local.host",
         "name":"Administrator",
-        "blocked":false,
+        "state":"active",
         "created_at":"2012-04-29T08:46:00Z"
     }
 }
@@ -97,7 +95,7 @@ Parameters:
 + `id` (required) - The ID of a project
 + `source_branch` (required) - The source branch
 + `target_branch` (required) - The target branch
-+ `assignee_id`              - Assignee user ID
++ `assignee_id` (optional)   - Assignee user ID
 + `title` (required)         - Title of MR
 
 ```json
@@ -107,14 +105,13 @@ Parameters:
     "source_branch":"test1",
     "project_id":3,
     "title":"test1",
-    "closed":true,
-    "merged":false,
+    "state":"opened",
     "author":{
         "id":1,
         "username": "admin",
         "email":"admin@local.host",
         "name":"Administrator",
-        "blocked":false,
+        "state":"active",
         "created_at":"2012-04-29T08:46:00Z"
     },
     "assignee":{
@@ -122,7 +119,7 @@ Parameters:
         "username": "admin",
         "email":"admin@local.host",
         "name":"Administrator",
-        "blocked":false,
+        "state":"active",
         "created_at":"2012-04-29T08:46:00Z"
     }
 }
@@ -145,24 +142,22 @@ Parameters:
 + `target_branch`               - The target branch
 + `assignee_id`                 - Assignee user ID
 + `title`                       - Title of MR
-+ `closed`                      - Status of MR. true - closed
-
 
 ```json
+
 {
     "id":1,
     "target_branch":"master",
     "source_branch":"test1",
     "project_id":3,
     "title":"test1",
-    "closed":true,
-    "merged":false,
+    "state":"opened",
     "author":{
         "id":1,
         "username": "admin",
         "email":"admin@local.host",
         "name":"Administrator",
-        "blocked":false,
+        "state":"active",
         "created_at":"2012-04-29T08:46:00Z"
     },
     "assignee":{
@@ -170,7 +165,7 @@ Parameters:
         "username": "admin",
         "email":"admin@local.host",
         "name":"Administrator",
-        "blocked":false,
+        "state":"active",
         "created_at":"2012-04-29T08:46:00Z"
     }
 }
diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md
index 04ea367d518..f7b7fc8fbb5 100644
--- a/doc/api/project_snippets.md
+++ b/doc/api/project_snippets.md
@@ -34,7 +34,7 @@ Parameters:
     "username": "john_smith",
     "email": "john@example.com",
     "name": "John Smith",
-    "blocked": false,
+    "state": "active",
     "created_at": "2012-05-23T08:00:58Z"
   },
   "expires_at": null,
-- 
GitLab


From 518565a12e8ca36f8187490ca6f9961ee43c7f91 Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Wed, 2 Oct 2013 12:08:07 +0200
Subject: [PATCH 219/248] Update issues, milestones, notes api docs.

---
 doc/api/issues.md     | 10 +++---
 doc/api/milestones.md | 15 +++++++++
 doc/api/notes.md      | 78 +++++++++++++++++++++++++++++++++++++++----
 3 files changed, 92 insertions(+), 11 deletions(-)

diff --git a/doc/api/issues.md b/doc/api/issues.md
index 314268b0fc0..9082cbb50ba 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -22,7 +22,7 @@ GET /issues
       "username": "john_smith",
       "email": "john@example.com",
       "name": "John Smith",
-      "blocked": false,
+      "state": "active",
       "created_at": "2012-05-23T08:00:58Z"
     },
     "state": "closed",
@@ -51,7 +51,7 @@ GET /issues
       "username": "jack_smith",
       "email": "jack@example.com",
       "name": "Jack Smith",
-      "blocked": false,
+      "state": "active",
       "created_at": "2012-05-23T08:01:01Z"
     },
     "author": {
@@ -59,7 +59,7 @@ GET /issues
       "username": "john_smith",
       "email": "john@example.com",
       "name": "John Smith",
-      "blocked": false,
+      "state": "active",
       "created_at": "2012-05-23T08:00:58Z"
     },
     "state": "opened",
@@ -120,7 +120,7 @@ Parameters:
     "username": "jack_smith",
     "email": "jack@example.com",
     "name": "Jack Smith",
-    "blocked": false,
+    "state": "active",
     "created_at": "2012-05-23T08:01:01Z"
   },
   "author": {
@@ -128,7 +128,7 @@ Parameters:
     "username": "john_smith",
     "email": "john@example.com",
     "name": "John Smith",
-    "blocked": false,
+    "state": "active",
     "created_at": "2012-05-23T08:00:58Z"
   },
   "state": "opened",
diff --git a/doc/api/milestones.md b/doc/api/milestones.md
index aa8f1bf5e02..2bdca68351b 100644
--- a/doc/api/milestones.md
+++ b/doc/api/milestones.md
@@ -6,6 +6,21 @@ Returns a list of project milestones.
 GET /projects/:id/milestones
 ```
 
+```json
+[
+  {
+    "id":12,
+    "project_id":16,
+    "title":"10.0",
+    "description":"Version",
+    "due_date":"2013-11-29",
+    "state":"active",
+    "updated_at":"2013-10-02T09:24:18Z",
+    "created_at":"2013-10-02T09:24:18Z"
+  }
+]
+```
+
 Parameters:
 
 + `id` (required) - The ID of a project
diff --git a/doc/api/notes.md b/doc/api/notes.md
index 4b57f636a01..397aa87aadf 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -8,17 +8,22 @@ Get a list of project wall notes.
 GET /projects/:id/notes
 ```
 
+Parameters:
+
++ `id` (required) - The ID of a project
+
 ```json
 [
   {
     "id": 522,
     "body": "The solution is rather tricky",
+    "attachment":null,
     "author": {
       "id": 1,
       "username": "john_smith",
       "email": "john@example.com",
       "name": "John Smith",
-      "blocked": false,
+      "state": "active",
       "created_at": "2012-05-23T08:00:58Z"
     },
     "created_at": "2012-11-27T19:16:44Z"
@@ -26,11 +31,6 @@ GET /projects/:id/notes
 ]
 ```
 
-Parameters:
-
-+ `id` (required) - The ID of a project
-
-
 ### Get single wall note
 
 Returns a single wall note.
@@ -74,6 +74,38 @@ Parameters:
 + `id` (required) - The ID of a project
 + `issue_id` (required) - The ID of an issue
 
+```json
+[
+  {
+    "id":302,
+    "body":"_Status changed to closed_",
+    "attachment":null,
+    "author":{
+      "id":1,
+      "username":"pipin",
+      "email":"admin@example.com",
+      "name":"Pip",
+      "state":"active",
+      "created_at":"2013-09-30T13:46:01Z"
+    },
+    "created_at":"2013-10-02T09:22:45Z"
+  },
+  {
+    "id":305,
+    "body":"Text of the comment\r\n",
+    "attachment":null,
+    "author":{
+      "id":1,
+      "username":"pipin",
+      "email":"admin@example.com",
+      "name":"Pip",
+      "state":"active",
+      "created_at":"2013-09-30T13:46:01Z"
+    },
+    "created_at":"2013-10-02T09:56:03Z"
+  }
+]
+```
 
 ### Get single issue note
 
@@ -135,6 +167,24 @@ Parameters:
 + `snippet_id` (required) - The ID of a project snippet
 + `note_id` (required) - The ID of an snippet note
 
+```json
+{
+  "id":52,
+  "title":"Snippet",
+  "file_name":"snippet.rb",
+  "author":{
+    "id":1,
+    "username":"pipin",
+    "email":"admin@example.com",
+    "name":"Pip",
+    "state":"active",
+    "created_at":"2013-09-30T13:46:01Z"
+  },
+  "expires_at":null,
+  "updated_at":"2013-10-02T07:34:20Z",
+  "created_at":"2013-10-02T07:34:20Z"
+}
+```
 
 ### Create new snippet note
 
@@ -181,6 +231,22 @@ Parameters:
 + `merge_request_id` (required) - The ID of a project merge request
 + `note_id` (required) - The ID of a merge request note
 
+```json
+{
+  "id":301,
+  "body":"Comment for MR",
+  "attachment":null,
+  "author":{
+    "id":1,
+    "username":"pipin",
+    "email":"admin@example.com",
+    "name":"Pip",
+    "state":"active",
+    "created_at":"2013-09-30T13:46:01Z"
+  },
+  "created_at":"2013-10-02T08:57:14Z"
+}
+```
 
 ### Create new merge request note
 
-- 
GitLab


From c0af3dae45bb7e246a46595a897fd4b9e54b9291 Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Wed, 2 Oct 2013 12:50:01 +0200
Subject: [PATCH 220/248] Update deploy keys, groups and system hooks api docs.

---
 doc/api/deploy_keys.md  |  7 +++++--
 doc/api/groups.md       | 12 ++++++------
 doc/api/system_hooks.md | 19 +++++++++++++++++++
 3 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md
index fbb1e45bccd..50d2b82c36f 100644
--- a/doc/api/deploy_keys.md
+++ b/doc/api/deploy_keys.md
@@ -20,13 +20,15 @@ Parameters:
     "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
       596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
       soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+    "created_at":"2013-10-02T10:12:29Z"
   },
   {
     "id": 3,
     "title" : "Another Public key",
     "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
       596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
-      soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+      soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+    "created_at":"2013-10-02T11:12:29Z"
   }
 ]
 ```
@@ -51,7 +53,8 @@ Parameters:
   "title" : "Public key",
   "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
       596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
-      soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+      soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+  "created_at":"2013-10-02T10:12:29Z"
 }
 ```
 
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 47c7c1bf4f5..460e75e7c29 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -8,12 +8,12 @@ GET /groups
 
 ```json
 [
-    {
-        "id": 1,
-        "name": "Foobar Group",
-        "path": "foo-bar",
-        "owner_id": 18
-    }
+  {
+    "id": 1,
+    "name": "Foobar Group",
+    "path": "foo-bar",
+    "owner_id": 18
+  }
 ]
 ```
 
diff --git a/doc/api/system_hooks.md b/doc/api/system_hooks.md
index dca22c43f83..5eeb3652d57 100644
--- a/doc/api/system_hooks.md
+++ b/doc/api/system_hooks.md
@@ -12,6 +12,15 @@ Parameters:
 
 + **none**
 
+```json
+[
+  {
+    "id":3,
+    "url":"http://example.com/hook",
+    "created_at":"2013-10-02T10:15:31Z"
+  }
+]
+```
 
 ## Add new system hook hook
 
@@ -34,6 +43,16 @@ Parameters:
 
 + `id` (required) - The ID of hook
 
+```json
+{
+  "event_name":"project_create",
+  "name":"Ruby",
+  "path":"ruby",
+  "project_id":1,
+  "owner_name":"Someone",
+  "owner_email":"example@gitlabhq.com"
+}
+```
 
 ## Delete system hook
 
-- 
GitLab


From 3c3b83ae8a532443bb8bdb4319396823faf539b3 Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Wed, 2 Oct 2013 12:51:43 +0200
Subject: [PATCH 221/248] Removed user teams api docs.

---
 doc/api/README.md     |   2 +-
 doc/api/user_teams.md | 209 ------------------------------------------
 2 files changed, 1 insertion(+), 210 deletions(-)
 delete mode 100644 doc/api/user_teams.md

diff --git a/doc/api/README.md b/doc/api/README.md
index 6971e08f010..ee24449343a 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -117,7 +117,7 @@ When listing resources you can pass the following parameters:
 + [Deploy Keys](deploy_keys.md)
 + [System Hooks](system_hooks.md)
 + [Groups](groups.md)
-+ [User Teams](user_teams.md)
+
 
 ## Clients
 
diff --git a/doc/api/user_teams.md b/doc/api/user_teams.md
deleted file mode 100644
index cf467a54667..00000000000
--- a/doc/api/user_teams.md
+++ /dev/null
@@ -1,209 +0,0 @@
-## User teams
-
-### List user teams
-
-Get a list of user teams viewable by the authenticated user.
-
-```
-GET /user_teams
-```
-
-```json
-[
-    {
-        id: 1,
-        name: "User team 1",
-        path: "user_team1",
-        owner_id: 1
-    },
-    {
-        id: 2,
-        name: "User team 2",
-        path: "user_team2",
-        owner_id: 1
-    }
-]
-```
-
-
-### Get single user team
-
-Get a specific user team, identified by user team ID, which is viewable by the authenticated user.
-
-```
-GET /user_teams/:id
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user_team
-
-```json
-{
-    id: 1,
-    name: "User team 1",
-    path: "user_team1",
-    owner_id: 1
-}
-```
-
-
-### Create user team
-
-Creates new user team owned by user. Available only for admins.
-
-```
-POST /user_teams
-```
-
-Parameters:
-
-+ `name` (required) - new user team name
-+ `path` (required) - new user team internal name
-
-
-
-## User team members
-
-### List user team members
-
-Get a list of project team members.
-
-```
-GET /user_teams/:id/members
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user_team
-
-
-### Get user team member
-
-Gets a user team member.
-
-```
-GET /user_teams/:id/members/:user_id
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user_team
-+ `user_id` (required) - The ID of a user
-
-```json
-{
-    id: 2,
-    username: "john_doe",
-    email: "joh@doe.org",
-    name: "John Doe",
-    state: "active",
-    created_at: "2012-10-22T14:13:35Z",
-    access_level: 30
-}
-```
-
-
-### Add user team member
-
-Adds a user to a user team.
-
-```
-POST /user_teams/:id/members
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user team
-+ `user_id` (required) - The ID of a user to add
-+ `access_level` (required) - Project access level
-
-
-### Remove user team member
-
-Removes user from user team.
-
-```
-DELETE /user_teams/:id/members/:user_id
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user team
-+ `user_id` (required) - The ID of a team member
-
-## User team projects
-
-### List user team projects
-
-Get a list of project team projects.
-
-```
-GET /user_teams/:id/projects
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user_team
-
-
-### Get user team project
-
-Gets a user team project.
-
-```
-GET /user_teams/:id/projects/:project_id
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user_team
-+ `project_id` (required) - The ID of a user
-
-```json
-{
-    id: 12,
-    name: "project1",
-    description: null,
-    default_branch: "develop",
-    public: false,
-    path: "project1",
-    path_with_namespace: "group1/project1",
-    issues_enabled: false,
-    merge_requests_enabled: true,
-    wall_enabled: true,
-    wiki_enabled: false,
-    created_at: "2013-03-11T12:59:08Z",
-    greatest_access_level: 30
-}
-```
-
-
-### Add user team project
-
-Adds a project to a user team.
-
-```
-POST /user_teams/:id/projects
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user team
-+ `project_id` (required) - The ID of a project to add
-+ `greatest_access_level` (required) - Maximum project access level
-
-
-### Remove user team project
-
-Removes project from user team.
-
-```
-DELETE /user_teams/:id/projects/:project_id
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user team
-+ `project_id` (required) - The ID of a team project
-
-- 
GitLab


From 8132aa5d5d6ab1cffdd23e6630525177c17a0480 Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Wed, 2 Oct 2013 14:43:11 +0200
Subject: [PATCH 222/248] Adapt readme to website redesign.

---
 README.md | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index ce0f4a8a1c5..961eca0ba9d 100644
--- a/README.md
+++ b/README.md
@@ -157,10 +157,8 @@ or start each component separately
 
 ### Getting in touch
 
-* [Core team](https://github.com/gitlabhq?tab=members)
+* [Core team](http://gitlab.org/team/)
 
-* [Contributors](https://github.com/gitlabhq/gitlabhq/graphs/contributors)
+* [Contributors](http://contributors.gitlab.org/)
 
-* [Leader](https://github.com/randx)
-
-* [Contact page](http://gitlab.org/contact/)
+* [Community](http://gitlab.org/community/)
-- 
GitLab


From 82dd12499daccdb06862f03aa9624d8c33ca603f Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Wed, 2 Oct 2013 15:02:54 +0200
Subject: [PATCH 223/248] Add direct link to backup task and some other
 interfaces.

---
 README.md | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 961eca0ba9d..b1c109950a0 100644
--- a/README.md
+++ b/README.md
@@ -127,14 +127,17 @@ or start each component separately
 
 ### GitLab interfaces
 
-* [GitLab API](doc/api/README.md)
+* [GitLab API doc](doc/api/README.md) or see the [GitLab API website](http://api.gitlab.org/)
 
-* [Rake tasks](doc/raketasks)
+* [Rake tasks](doc/raketasks) including a [backup and restore procedure](doc/raketasks/backup_restore.md)
 
 * [Directory structure](doc/install/structure.md)
 
-* [Databases](doc/install/databases.md)
+* [Database installation](doc/install/databases.md)
 
+* [Markdown specification](doc/markdown/markdown.md)
+
+* [Security guide](doc/security/rack_attack.md) to throttle abusive requests
 
 ### Getting help
 
-- 
GitLab


From 8a3faf57671a8db6699abfcce8d94a1472b0ca4f Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Wed, 2 Oct 2013 16:41:01 +0200
Subject: [PATCH 224/248] Update group access levels in docs.

---
 doc/api/groups.md   | 13 +++++++++++++
 doc/api/projects.md | 12 ------------
 2 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/doc/api/groups.md b/doc/api/groups.md
index 460e75e7c29..f56c534667a 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -59,6 +59,19 @@ Parameters:
 
 ## Group members
 
+
+**Group access levels**
+
+The group access levels are defined in the `Gitlab::Access` module. Currently, these levels are recognized:
+
+```
+  GUEST     = 10
+  REPORTER  = 20
+  DEVELOPER = 30
+  MASTER    = 40
+  OWNER     = 50
+```
+
 ### List group members
 
 Get a list of group members viewable by the authenticated user.
diff --git a/doc/api/projects.md b/doc/api/projects.md
index d247c07ece4..0f73fb434da 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -221,18 +221,6 @@ Parameters:
 + `snippets_enabled` (optional)
 + `public` (optional)
 
-**Project access levels**
-
-The project access levels are defined in the `Gitlab::Access` module. Currently, these levels are recognized:
-
-```
-  GUEST     = 10
-  REPORTER  = 20
-  DEVELOPER = 30
-  MASTER    = 40
-  OWNER     = 50
-```
-
 
 ### Create project for user
 
-- 
GitLab


From 92ae62882faee4d3d8881127c691cfae7763b076 Mon Sep 17 00:00:00 2001
From: Yatish Mehta <yatishmehta27@gmail.com>
Date: Thu, 3 Oct 2013 14:34:51 +0530
Subject: [PATCH 225/248] Typo:Corrected the typo of sign-in in User Model

---
 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 f1f93eadc1a..c61b074f504 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -167,7 +167,7 @@ class User < ActiveRecord::Base
   # Class methods
   #
   class << self
-    # Devise method overridden to allow sing in with email or username
+    # Devise method overridden to allow sign in with email or username
     def find_for_database_authentication(warden_conditions)
       conditions = warden_conditions.dup
       if login = conditions.delete(:login)
-- 
GitLab


From bf2a2d89217c5356cb64509813e60f1c0d3d209b Mon Sep 17 00:00:00 2001
From: Boyan Tabakov <boyan.tabakov@futurice.com>
Date: Thu, 3 Oct 2013 16:29:13 +0300
Subject: [PATCH 226/248] Use gitlab-flowdock-git-hook patched for dependency
 on gitlab-grit, instead of grit.

Make sure the flowdock-git-hook is loaded. Seems it is not autoloader, due to the gem/lib name mismatch.
---
 Gemfile                        |  2 +-
 Gemfile.lock                   | 12 ++++--------
 app/models/flowdock_service.rb |  2 ++
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/Gemfile b/Gemfile
index 50ce0c14570..fb67f301f72 100644
--- a/Gemfile
+++ b/Gemfile
@@ -112,7 +112,7 @@ gem 'tinder', '~> 1.9.2'
 gem "hipchat", "~> 0.9.0"
 
 # Flowdock integration
-gem "flowdock-git-hook", "~> 0.4.2"
+gem "gitlab-flowdock-git-hook", "~> 0.4.2"
 
 # d3
 gem "d3_rails", "~> 3.1.4"
diff --git a/Gemfile.lock b/Gemfile.lock
index f39aeb6ec2a..ce3aeb7994b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -130,9 +130,6 @@ GEM
       faraday (>= 0.7.4, < 0.9)
     ffaker (1.18.0)
     ffi (1.9.0)
-    flowdock-git-hook (0.4.2)
-      grit (>= 2.4.1)
-      multi_json
     fog (1.3.1)
       builder
       excon (~> 0.13.0)
@@ -159,6 +156,9 @@ GEM
       pygments.rb (>= 0.2.13)
     github-markdown (0.5.3)
     github-markup (0.7.5)
+    gitlab-flowdock-git-hook (0.4.2.2)
+      gitlab-grit (>= 2.4.1)
+      multi_json
     gitlab-gollum-lib (1.0.1)
       github-markdown (~> 0.5.3)
       github-markup (>= 0.7.5, < 1.0.0)
@@ -203,10 +203,6 @@ GEM
     grape-entity (0.3.0)
       activesupport
       multi_json (>= 1.3.2)
-    grit (2.5.0)
-      diff-lcs (~> 1.1)
-      mime-types (~> 1.15)
-      posix-spawn (~> 0.3.6)
     growl (1.0.3)
     guard (1.8.1)
       formatador (>= 0.2.4)
@@ -572,13 +568,13 @@ DEPENDENCIES
   enumerize
   factory_girl_rails
   ffaker
-  flowdock-git-hook (~> 0.4.2)
   fog (~> 1.3.1)
   font-awesome-rails
   foreman
   gemoji (~> 1.2.1)
   github-linguist
   github-markup (~> 0.7.4)
+  gitlab-flowdock-git-hook (~> 0.4.2)
   gitlab-gollum-lib (~> 1.0.1)
   gitlab-grack (~> 1.0.1)
   gitlab-pygments.rb (~> 0.3.2)
diff --git a/app/models/flowdock_service.rb b/app/models/flowdock_service.rb
index 143e986ca75..6ec431d4a10 100644
--- a/app/models/flowdock_service.rb
+++ b/app/models/flowdock_service.rb
@@ -13,6 +13,8 @@
 #  project_url :string(255)
 #
 
+require "flowdock-git-hook"
+
 class FlowdockService < Service
   validates :token, presence: true, if: :activated?
 
-- 
GitLab


From 1822c7d45466269e84268d237d2290b4ded30634 Mon Sep 17 00:00:00 2001
From: Jacob Vosmaer <contact@jacobvosmaer.nl>
Date: Fri, 4 Oct 2013 11:18:44 +0200
Subject: [PATCH 227/248] Only kill sidekiqs belonging to gitlab user

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

diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 4ae0e1fc5f9..c71e821a1cb 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -289,7 +289,6 @@ namespace :gitlab do
     ########################
 
     def check_gitlab_git_config
-      gitlab_user = Gitlab.config.gitlab.user
       print "Git configured for #{gitlab_user} user? ... "
 
       options = {
@@ -646,8 +645,8 @@ namespace :gitlab do
         puts "#{sidekiq_match.length}".red
         try_fixing_it(
           'sudo service gitlab stop',
-          'sudo pkill -f sidekiq',
-          'sleep 10 && sudo pkill -9 -f sidekiq',
+          "sudo pkill -u #{gitlab_user} -f sidekiq",
+          "sleep 10 && sudo pkill -9 -u #{gitlab_user} -f sidekiq",
           'sudo service gitlab start'
         )
         fix_and_rerun
@@ -691,10 +690,13 @@ namespace :gitlab do
   end
 
   def sudo_gitlab(command)
-    gitlab_user = Gitlab.config.gitlab.user
     "sudo -u #{gitlab_user} -H #{command}"
   end
 
+  def gitlab_user
+    Gitlab.config.gitlab.user
+  end
+
   def start_checking(component)
     puts "Checking #{component.yellow} ..."
     puts ""
-- 
GitLab


From 04396761735fe778b1ef1e578462da273541a5dc Mon Sep 17 00:00:00 2001
From: Sytse Sijbrandij <sytse@dosire.com>
Date: Fri, 4 Oct 2013 12:20:40 +0200
Subject: [PATCH 228/248] Better requirements based on the experience of GitLab
 Cloud.

---
 doc/install/requirements.md | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 1dba04f4237..30a95646741 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -41,23 +41,30 @@ some work on your part.
 
 ## CPU
 
-We recommend a processor with **4 cores**. At a minimum you need a processor with 2 cores to responsively run an unmodified installation.
+- 1 core works for under 100 users but the responsiveness might suffer
+- **2 cores** is the **recommended** number of cores and supports up to 100 users
+- 4 cores supports about 1,000 users
+- 8 cores supports up to 10,000 users
 
 ## Memory
 
 - 512MB is too little memory, GitLab will be very slow and you will need 250MB of swap
-- 768MB is the minimal memory size and supports up to 100 users
-- **1GB** is the **recommended** memory size and supports up to 1,000 users
-- 1.5GB supports up to 10,000 users
+- 768MB is the minimal memory size but we advise against this
+- 1GB supports up to 100 users if you do not have individual repo's over 250MB
+- **2GB** is the **recommended** memory size and supports up to 1,000 users
+- 4GB supports up to 10,000 users
 
 ## Storage
 
 The necessary hard drive space largely depends on the size of the repos you want
 to store in GitLab. But as a *rule of thumb* you should have at least twice as much
-free space as your all repos combined take up. You need twice the storage because [GitLab satellites](structure.md) contain an extra copy of each repo. Apart from a local hard drive you can also mount a volume that supports the network file system (NFS) protocol. This volume might be located on a file server, a network attached storage (NAS) device, a storage area network (SAN) or on an Amazon Web Services (AWS) Elastic Block Store (EBS) volume.
+free space as your all repos combined take up. You need twice the storage because [GitLab satellites](structure.md) contain an extra copy of each repo.
 
-If you have enough RAM memory and a recent CPU the speed of GitLab is mainly limited by hard drive seek times. Having a fast drive (7200 RPM and up) or a solid state drive (SSD) will improve the responsiveness of GitLab.
+If you want to be flexible about growing your hard drive space in the future consider mounting it using LVM so you can add more hard drives when you need them.
+
+Apart from a local hard drive you can also mount a volume that supports the network file system (NFS) protocol. This volume might be located on a file server, a network attached storage (NAS) device, a storage area network (SAN) or on an Amazon Web Services (AWS) Elastic Block Store (EBS) volume.
 
+If you have enough RAM memory and a recent CPU the speed of GitLab is mainly limited by hard drive seek times. Having a fast drive (7200 RPM and up) or a solid state drive (SSD) will improve the responsiveness of GitLab.
 
 # Installation troubles and reporting success or failure
 
-- 
GitLab


From 6ff4f1615d4d451278fa6bbf82610003363b27e1 Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Fri, 4 Oct 2013 12:38:49 +0200
Subject: [PATCH 229/248] Fix failed merge when filename is the same as target
 branchname.

---
 lib/gitlab/satellite/merge_action.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/gitlab/satellite/merge_action.rb b/lib/gitlab/satellite/merge_action.rb
index 156483be8dd..5d56852f058 100644
--- a/lib/gitlab/satellite/merge_action.rb
+++ b/lib/gitlab/satellite/merge_action.rb
@@ -149,7 +149,7 @@ module Gitlab
           # We can't trust the input here being branch names, we can't always check it out because it could be a relative ref i.e. HEAD~3
           # we could actually remove the if true, because it should never ever happen (as long as the satellite has been prepared)
           repo.git.checkout(default_options, "#{merge_request.source_branch}")
-          repo.git.checkout(default_options, "#{merge_request.target_branch}")
+          repo.git.checkout(default_options({t: true}), "origin/#{merge_request.target_branch}")
         end
       rescue Grit::Git::CommandFailed => ex
         handle_exception(ex)
-- 
GitLab


From db9cf1ba83e57cae77c7cdb053056d2e436f4a9c Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Fri, 4 Oct 2013 13:26:48 +0200
Subject: [PATCH 230/248] Remove outdated comments.

---
 lib/gitlab/satellite/merge_action.rb | 2 --
 1 file changed, 2 deletions(-)

diff --git a/lib/gitlab/satellite/merge_action.rb b/lib/gitlab/satellite/merge_action.rb
index 5d56852f058..d74d4194ff6 100644
--- a/lib/gitlab/satellite/merge_action.rb
+++ b/lib/gitlab/satellite/merge_action.rb
@@ -146,8 +146,6 @@ module Gitlab
           repo.remote_fetch('source')
           repo.git.checkout(default_options({b: true}), merge_request.target_branch, "origin/#{merge_request.target_branch}")
         else
-          # We can't trust the input here being branch names, we can't always check it out because it could be a relative ref i.e. HEAD~3
-          # we could actually remove the if true, because it should never ever happen (as long as the satellite has been prepared)
           repo.git.checkout(default_options, "#{merge_request.source_branch}")
           repo.git.checkout(default_options({t: true}), "origin/#{merge_request.target_branch}")
         end
-- 
GitLab


From 4ddd316a2b88b307c62fccaf214859bc9f8ff1e4 Mon Sep 17 00:00:00 2001
From: Jacob Vosmaer <contact@jacobvosmaer.nl>
Date: Mon, 7 Oct 2013 11:27:38 +0200
Subject: [PATCH 231/248] Add troubleshooting hints to update hook check

---
 lib/tasks/gitlab/check.rake | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index c71e821a1cb..3396c7102eb 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -391,14 +391,20 @@ namespace :gitlab do
       hook_file = "update"
       gitlab_shell_hooks_path = Gitlab.config.gitlab_shell.hooks_path
       gitlab_shell_hook_file  = File.join(gitlab_shell_hooks_path, hook_file)
-      gitlab_shell_ssh_user = Gitlab.config.gitlab_shell.ssh_user
 
-      unless File.exists?(gitlab_shell_hook_file)
-        puts "can't check because of previous errors".magenta
-        return
+      if File.exists?(gitlab_shell_hook_file)
+        puts "yes".green
+      else
+        puts "no".red
+        puts "Could not find #{gitlab_shell_hook_file}"
+        try_fixing_it(
+          'Check the hooks_path in config/gitlab.yml',
+          'Check your gitlab-shell installation'
+        )
+        for_more_information(
+          see_installation_guide_section "GitLab Shell"
+        )
       end
-
-      puts "yes".green
     end
 
     def check_repo_base_exists
-- 
GitLab


From d0762f8714fbc11b67e7634ec4edc90e2ad45309 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 7 Oct 2013 13:10:01 +0300
Subject: [PATCH 232/248] API: new feature - remove group

---
 doc/api/groups.md | 13 +++++++++++++
 lib/api/groups.rb | 18 ++++++++++++++++--
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/doc/api/groups.md b/doc/api/groups.md
index f56c534667a..f5f5d769050 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -57,6 +57,19 @@ Parameters:
 + `project_id` (required) - The ID of a project
 
 
+## Remove group
+
+Removes group with all projects inside.
+
+```
+DELETE /groups/:id
+```
+
+Parameters:
+
++ `id` (required) - The ID of a user group
+
+
 ## Group members
 
 
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 396554404af..265417fd6bc 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -7,12 +7,14 @@ module API
       helpers do
         def find_group(id)
           group = Group.find(id)
-          if current_user.admin or current_user.groups.include? group
+
+          if can?(current_user, :read_group, group)
             group
           else
             render_api_error!("403 Forbidden - #{current_user.username} lacks sufficient access to #{group.name}", 403)
           end
         end
+
         def validate_access_level?(level)
           Gitlab::Access.options_with_owner.values.include? level.to_i
         end
@@ -64,6 +66,19 @@ module API
         present group, with: Entities::GroupDetail
       end
 
+
+      # Remove group
+      #
+      # Parameters:
+      #   id (required) - The ID of a group
+      # Example Request:
+      #   DELETE /groups/:id
+      delete ":id" do
+        group = find_group(params[:id])
+        authorize! :manage_group, group
+        group.destroy
+      end
+
       # Transfer a project to the Group namespace
       #
       # Parameters:
@@ -132,7 +147,6 @@ module API
           member.destroy
         end
       end
-
     end
   end
 end
-- 
GitLab


From b46c2c38429c462186ca068b87a06434226cc403 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 7 Oct 2013 13:18:37 +0300
Subject: [PATCH 233/248] Remove group api specs

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

diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index a6ce72e11e9..25b9a10bd8c 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -106,6 +106,44 @@ describe API::API do
     end
   end
 
+  describe "DELETE /groups/:id" do
+    context "when authenticated as user" do
+      it "should remove group" do
+        delete api("/groups/#{group1.id}", user1)
+        response.status.should == 200
+      end
+
+      it "should not remove a group if not an owner" do
+        user3 = create(:user)
+        group1.add_user(user3, Gitlab::Access::MASTER)
+        delete api("/groups/#{group1.id}", user3)
+        response.status.should == 403
+      end
+
+      it "should not remove a non existing group" do
+        delete api("/groups/1328", user1)
+        response.status.should == 404
+      end
+
+      it "should not remove a group not attached to user1" do
+        delete api("/groups/#{group2.id}", user1)
+        response.status.should == 403
+      end
+    end
+
+    context "when authenticated as admin" do
+      it "should remove any existing group" do
+        delete api("/groups/#{group2.id}", admin)
+        response.status.should == 200
+      end
+
+      it "should not remove a non existing group" do
+        delete api("/groups/1328", admin)
+        response.status.should == 404
+      end
+    end
+  end
+
   describe "POST /groups/:id/projects/:project_id" do
     let(:project) { create(:project) }
     before(:each) do
-- 
GitLab


From cd12b5ef3805865d59ac73c2136ec6e0f69f14e4 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 7 Oct 2013 13:27:32 +0300
Subject: [PATCH 234/248] Mention remove group api in CHANGELOG

---
 CHANGELOG | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG b/CHANGELOG
index c1107717fc8..c4e411e2df5 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -12,6 +12,7 @@ v 6.2.0
   - Update logic for validates_merge_request for tree of MR (Andrew Kumanyaev)
   - Rake tasks for web hooks management (Jonhnny Weslley)
   - Extended User API to expose admin and can_create_group for user creation/updating (Boyan Tabakov)
+  - API: Remove group
 
 v 6.1.0
   - Project specific IDs for issues, mr, milestones
-- 
GitLab


From c94fe867509e10f003e4bec6900b3bfd858d36c1 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 7 Oct 2013 14:49:01 +0300
Subject: [PATCH 235/248] Fix bugs when discussion visible in wrong project

Because notes scope was not limited by project in
MergeRequest#mr_and_commit_notes it causes comments from project A
appears in discussions for MR in project B.
---
 app/models/merge_request.rb | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index a26190015b2..b164ea11073 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -222,7 +222,11 @@ class MergeRequest < ActiveRecord::Base
 
   def mr_and_commit_notes
     commit_ids = commits.map(&:id)
-    Note.where("(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))", mr_id: id, commit_ids: commit_ids)
+    project.notes.where(
+      "(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))",
+      mr_id: id,
+      commit_ids: commit_ids
+    )
   end
 
   # Returns the raw diff for this merge request
-- 
GitLab


From dd6e4bc68c886407c5163e60fccf47d3544446f6 Mon Sep 17 00:00:00 2001
From: Jacob Vosmaer <contact@jacobvosmaer.nl>
Date: Mon, 7 Oct 2013 14:16:04 +0200
Subject: [PATCH 236/248] Fix sudo commands in update guides

---
 doc/update/5.1-to-5.2.md | 4 ++--
 doc/update/5.2-to-5.3.md | 4 ++--
 doc/update/5.3-to-5.4.md | 4 ++--
 doc/update/5.4-to-6.0.md | 2 +-
 doc/update/6.0-to-6.1.md | 4 ++--
 doc/update/6.1-to-6.2.md | 4 ++--
 6 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/doc/update/5.1-to-5.2.md b/doc/update/5.1-to-5.2.md
index 8599c4323ea..27f992ecfe6 100644
--- a/doc/update/5.1-to-5.2.md
+++ b/doc/update/5.1-to-5.2.md
@@ -7,7 +7,7 @@ It's useful to make a backup just in case things go south:
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
 ```
 
 ### 1. Stop server
@@ -95,5 +95,5 @@ Follow the [`upgrade guide from 5.0 to 5.1`](5.0-to-5.1.md), except for the data
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
 ```
diff --git a/doc/update/5.2-to-5.3.md b/doc/update/5.2-to-5.3.md
index e00dfa3951a..a8bb530902c 100644
--- a/doc/update/5.2-to-5.3.md
+++ b/doc/update/5.2-to-5.3.md
@@ -7,7 +7,7 @@ It's useful to make a backup just in case things go south:
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
 ```
 
 ### 1. Stop server
@@ -78,5 +78,5 @@ Follow the [`upgrade guide from 5.1 to 5.2`](5.1-to-5.2.md), except for the data
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
 ```
diff --git a/doc/update/5.3-to-5.4.md b/doc/update/5.3-to-5.4.md
index 5fba0e26afa..315bf03a6de 100644
--- a/doc/update/5.3-to-5.4.md
+++ b/doc/update/5.3-to-5.4.md
@@ -7,7 +7,7 @@ It's useful to make a backup just in case things go south:
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
 ```
 
 ### 1. Stop server
@@ -86,5 +86,5 @@ Follow the [`upgrade guide from 5.2 to 5.3`](5.2-to-5.3.md), except for the data
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
 ```
diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md
index 3b1d9878204..0027d91d60a 100644
--- a/doc/update/5.4-to-6.0.md
+++ b/doc/update/5.4-to-6.0.md
@@ -24,7 +24,7 @@ It's useful to make a backup just in case things go south:
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
 ```
 
 ### 1. Stop server
diff --git a/doc/update/6.0-to-6.1.md b/doc/update/6.0-to-6.1.md
index 9ec99af205b..c3851a10df0 100644
--- a/doc/update/6.0-to-6.1.md
+++ b/doc/update/6.0-to-6.1.md
@@ -16,7 +16,7 @@ It's useful to make a backup just in case things go south:
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
 ```
 
 ### 1. Stop server
@@ -99,5 +99,5 @@ Follow the [`upgrade guide from 5.4 to 6.0`](5.4-to-6.0.md), except for the data
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
 ```
diff --git a/doc/update/6.1-to-6.2.md b/doc/update/6.1-to-6.2.md
index 747b4860796..9f3a869a0ee 100644
--- a/doc/update/6.1-to-6.2.md
+++ b/doc/update/6.1-to-6.2.md
@@ -9,7 +9,7 @@ It's useful to make a backup just in case things go south:
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
 ```
 
 ### 1. Stop server
@@ -96,5 +96,5 @@ Follow the [`upgrade guide from 6.0 to 6.1`](6.0-to-6.1.md), except for the data
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
 ```
-- 
GitLab


From 592aff2d402e394b9c0dd5f1c4a04bd3290d3c42 Mon Sep 17 00:00:00 2001
From: Jacob Vosmaer <contact@jacobvosmaer.nl>
Date: Mon, 7 Oct 2013 13:32:33 +0200
Subject: [PATCH 237/248] Run stopping commands in the foreground

---
 lib/support/init.d/gitlab | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
index 0248284f8d5..6aff7b5a8f9 100755
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -151,7 +151,7 @@ stop() {
   exit_if_not_running
   # If the Unicorn web server is running, tell it to stop;
   if [ "$web_status" = "0" ]; then
-    kill -QUIT "$wpid" &
+    kill -QUIT "$wpid"
     echo "Stopping the GitLab Unicorn web server..."
     stopping=true
   else
@@ -160,7 +160,7 @@ stop() {
   # And do the same thing for the Sidekiq.
   if [ "$sidekiq_status" = "0" ]; then
     printf "Stopping Sidekiq job dispatcher."
-    RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop &
+    RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop
     stopping=true
   else
     echo "The Sidekiq was not running, must have run out of breath."
-- 
GitLab


From b7fbaa7589cc2122dc764bd07bfe5070573ea8e4 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 7 Oct 2013 16:06:30 +0300
Subject: [PATCH 238/248] Check if LDAP user was removed or blocked when use
 git over ssh

---
 lib/api/internal.rb     |  1 +
 lib/gitlab/ldap/user.rb | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index 79f8eb3a543..ed6b50c3a6a 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -35,6 +35,7 @@ module API
           user = key.user
 
           return false if user.blocked?
+          return false if user.ldap_user? && Gitlab::LDAP::User.blocked?(user.extern_uid)
 
           action = case git_cmd
                    when *DOWNLOAD_COMMANDS
diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
index 260bacfeeb0..78fc5dab9cb 100644
--- a/lib/gitlab/ldap/user.rb
+++ b/lib/gitlab/ldap/user.rb
@@ -71,6 +71,16 @@ module Gitlab
           find_by_uid(ldap_user.dn) if ldap_user
         end
 
+        # Check LDAP user existance by dn. User in git over ssh check
+        #
+        # It covers 2 cases:
+        # * when ldap account was removed
+        # * when ldap account was deactivated by change of OU membership in 'dn'
+        def blocked?(dn)
+          ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
+          ldap.connection.search(base: dn, size: 1).blank?
+        end
+
         private
 
         def find_by_uid(uid)
-- 
GitLab


From a586ee47f587e17f71bd392702b3b1e7b839cf41 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 7 Oct 2013 16:56:02 +0300
Subject: [PATCH 239/248] Fix avatar margin for files view

---
 app/assets/stylesheets/sections/tree.scss             | 5 -----
 app/views/projects/tree/_tree_commit_column.html.haml | 2 +-
 2 files changed, 1 insertion(+), 6 deletions(-)

diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss
index 2a84741f0d6..96f2a5711fa 100644
--- a/app/assets/stylesheets/sections/tree.scss
+++ b/app/assets/stylesheets/sections/tree.scss
@@ -65,11 +65,6 @@
 
   .tree_author {
     padding-right: 8px;
-
-    img.avatar {
-      margin-top: 0;
-      width: 16px;
-    }
   }
 
   .tree_commit {
diff --git a/app/views/projects/tree/_tree_commit_column.html.haml b/app/views/projects/tree/_tree_commit_column.html.haml
index 7ae2582c130..67b5b2b96e2 100644
--- a/app/views/projects/tree/_tree_commit_column.html.haml
+++ b/app/views/projects/tree/_tree_commit_column.html.haml
@@ -1,2 +1,2 @@
-%span.tree_author= commit_author_link(commit, avatar: true)
+%span.tree_author= commit_author_link(commit, avatar: true, size: 16)
 = link_to_gfm truncate(commit.title, length: 80), project_commit_path(@project, commit.id), class: "tree-commit-link"
-- 
GitLab


From f0a1e4eb0fc2a690d246e7e3e40562022c8668df Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 7 Oct 2013 19:42:59 +0300
Subject: [PATCH 240/248] Fix merge request model spec

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

diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 703f46adba3..b17183a281c 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -49,8 +49,8 @@ describe MergeRequest do
 
     before do
       merge_request.stub(:commits) { [merge_request.source_project.repository.commit] }
-      create(:note, commit_id: merge_request.commits.first.id, noteable_type: 'Commit')
-      create(:note, noteable: merge_request)
+      create(:note, commit_id: merge_request.commits.first.id, noteable_type: 'Commit', project: merge_request.project)
+      create(:note, noteable: merge_request, project: merge_request.project)
     end
 
     it "should include notes for commits" do
-- 
GitLab


From 7ce7322238cb2f04b3805a119edb99741073a69b Mon Sep 17 00:00:00 2001
From: Islam Amer <islam.amer@jollamobile.com>
Date: Mon, 2 Sep 2013 15:36:05 +0000
Subject: [PATCH 241/248] Expose votes in merge request api

Signed-off-by: Islam Amer <islam.amer@jollamobile.com>
---
 doc/api/merge_requests.md | 8 ++++++++
 lib/api/entities.rb       | 2 +-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index e69d4bc99b9..dae12f03ef5 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -20,6 +20,8 @@ Parameters:
         "project_id":3,
         "title":"test1",
         "state":"opened",
+        "upvotes":0,
+        "downvotes":0,
         "author":{
             "id":1,
             "username": "admin",
@@ -62,6 +64,8 @@ Parameters:
     "project_id":3,
     "title":"test1",
     "state":"merged",
+    "upvotes":0,
+    "downvotes":0,
     "author":{
         "id":1,
         "username": "admin",
@@ -106,6 +110,8 @@ Parameters:
     "project_id":3,
     "title":"test1",
     "state":"opened",
+    "upvotes":0,
+    "downvotes":0,
     "author":{
         "id":1,
         "username": "admin",
@@ -152,6 +158,8 @@ Parameters:
     "project_id":3,
     "title":"test1",
     "state":"opened",
+    "upvotes":0,
+    "downvotes":0,
     "author":{
         "id":1,
         "username": "admin",
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index ab949f530ab..b4771eecc7f 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -112,7 +112,7 @@ module API
     end
 
     class MergeRequest < Grape::Entity
-      expose :id, :target_branch, :source_branch, :title, :state
+      expose :id, :target_branch, :source_branch, :title, :state, :upvotes, :downvotes
       expose :target_project_id, as: :project_id
       expose :author, :assignee, using: Entities::UserBasic
     end
-- 
GitLab


From d7fb4e4f3b073d7cf5c6cfedec4b43ed6f89815b Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 8 Oct 2013 10:54:40 +0300
Subject: [PATCH 242/248] Add user_id to system hook when new user created

---
 app/services/system_hooks_service.rb       | 3 ++-
 spec/services/system_hooks_service_spec.rb | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb
index 39aec943f75..de4fa9b79e7 100644
--- a/app/services/system_hooks_service.rb
+++ b/app/services/system_hooks_service.rb
@@ -36,7 +36,8 @@ class SystemHooksService
     when User
       data.merge!({
         name: model.name,
-        email: model.email
+        email: model.email,
+        user_id: model.id
       })
     when UsersProject
       data.merge!({
diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb
index 7f1590f559e..fb52b216cb4 100644
--- a/spec/services/system_hooks_service_spec.rb
+++ b/spec/services/system_hooks_service_spec.rb
@@ -7,7 +7,7 @@ describe SystemHooksService do
 
   context 'it should build event data' do
     it 'should build event data for user' do
-      SystemHooksService.build_event_data(user, :create).should include(:event_name, :name, :created_at, :email)
+      SystemHooksService.build_event_data(user, :create).should include(:event_name, :name, :created_at, :email, :user_id)
     end
 
     it 'should build event data for project' do
-- 
GitLab


From ad1d31f4295ce9ea85269a35905412abd25c2f78 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 8 Oct 2013 11:06:38 +0300
Subject: [PATCH 243/248] Mention SystemHook user_id in sample. Extend tests

---
 app/views/admin/hooks/_data_ex.html.erb    |  6 ++-
 spec/services/system_hooks_service_spec.rb | 48 +++++++++-------------
 2 files changed, 24 insertions(+), 30 deletions(-)

diff --git a/app/views/admin/hooks/_data_ex.html.erb b/app/views/admin/hooks/_data_ex.html.erb
index b69aa92716d..5b16dfb398a 100644
--- a/app/views/admin/hooks/_data_ex.html.erb
+++ b/app/views/admin/hooks/_data_ex.html.erb
@@ -52,7 +52,8 @@
    "created_at": "2012-07-21T07:44:07Z",
         "email": "js@gitlabhq.com",
    "event_name": "user_create",
-         "name": "John Smith" 
+         "name": "John Smith", 
+      "user_id": 41 
 }
 
 6. User removed:
@@ -60,7 +61,8 @@
    "created_at": "2012-07-21T07:44:07Z",
         "email": "js@gitlabhq.com",
    "event_name": "user_destroy",
-         "name": "John Smith" 
+         "name": "John Smith",
+      "user_id": 41 
 }
 
 eos
diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb
index fb52b216cb4..ebc1ed51d2e 100644
--- a/spec/services/system_hooks_service_spec.rb
+++ b/spec/services/system_hooks_service_spec.rb
@@ -5,37 +5,29 @@ describe SystemHooksService do
   let (:project)       { create :project }
   let (:users_project) { create :users_project }
 
-  context 'it should build event data' do
-    it 'should build event data for user' do
-      SystemHooksService.build_event_data(user, :create).should include(:event_name, :name, :created_at, :email, :user_id)
-    end
-
-    it 'should build event data for project' do
-      SystemHooksService.build_event_data(project, :create).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email)
-    end
-
-    it 'should build event data for users project' do
-      SystemHooksService.build_event_data(users_project, :create).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :project_access)
-    end
+  context 'event data' do
+    it { event_data(user, :create).should include(:event_name, :name, :created_at, :email, :user_id) }
+    it { event_data(user, :destroy).should include(:event_name, :name, :created_at, :email, :user_id) }
+    it { event_data(project, :create).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email) }
+    it { event_data(project, :destroy).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email) }
+    it { event_data(users_project, :create).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :project_access) }
+    it { event_data(users_project, :destroy).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :project_access) }
   end
 
-  context 'it should build event names' do
-    it 'should build event names for user' do
-      SystemHooksService.build_event_name(user, :create).should eq "user_create"
-
-      SystemHooksService.build_event_name(user, :destroy).should eq "user_destroy"
-    end
-
-    it 'should build event names for project' do
-      SystemHooksService.build_event_name(project, :create).should eq "project_create"
-
-      SystemHooksService.build_event_name(project, :destroy).should eq "project_destroy"
-    end
+  context 'event names' do
+    it { event_name(user, :create).should eq "user_create" }
+    it { event_name(user, :destroy).should eq "user_destroy" }
+    it { event_name(project, :create).should eq "project_create" }
+    it { event_name(project, :destroy).should eq "project_destroy" }
+    it { event_name(users_project, :create).should eq "user_add_to_team" }
+    it { event_name(users_project, :destroy).should eq "user_remove_from_team" }
+  end
 
-    it 'should build event names for users project' do
-      SystemHooksService.build_event_name(users_project, :create).should eq "user_add_to_team"
+  def event_data(*args)
+    SystemHooksService.build_event_data(*args)
+  end
 
-      SystemHooksService.build_event_name(users_project, :destroy).should eq "user_remove_from_team"
-    end
+  def event_name(*args)
+    SystemHooksService.build_event_name(*args)
   end
 end
-- 
GitLab


From 1c4b6d78c446feda440270198fdb409f14fe76b5 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 8 Oct 2013 12:06:46 +0300
Subject: [PATCH 244/248] Fix system hook page description

---
 app/views/admin/hooks/index.html.haml | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml
index eb6570af30e..1bd7b8eac62 100644
--- a/app/views/admin/hooks/index.html.haml
+++ b/app/views/admin/hooks/index.html.haml
@@ -1,9 +1,12 @@
-.alert.alert-info
-  %span
-    Post-receive hooks for binding events.
-    %br
-    Read more about system hooks
-    %strong #{link_to "here", help_system_hooks_path, class: "vlink"}
+%h3.page-title
+  System Hooks
+
+%p.light
+  #{link_to "System hooks ", help_system_hooks_path, class: "vlink"} can be
+  used for binding events when GitLab creates a User or Project.
+
+%hr
+
 
 = form_for @hook, as: :hook, url: admin_hooks_path, html: { class: 'form-inline' } do |f|
   -if @hook.errors.any?
-- 
GitLab


From 5221bbf187abf5b7f9437edfd02c2ae812d58aee Mon Sep 17 00:00:00 2001
From: Andrew Kumanyaev <me@zzet.org>
Date: Tue, 8 Oct 2013 16:45:57 +0400
Subject: [PATCH 245/248] Update merge requests from fork project to origin
 project

Fix error described in https://github.com/gitlabhq/gitlabhq/issues/5185
---
 app/models/project.rb | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/app/models/project.rb b/app/models/project.rb
index 8755ffa69b8..d2dcf26ac69 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -53,6 +53,7 @@ class Project < ActiveRecord::Base
   has_many :services,           dependent: :destroy
   has_many :events,             dependent: :destroy
   has_many :merge_requests,     dependent: :destroy, foreign_key: "target_project_id"
+  has_many :fork_merge_requests,dependent: :destroy, foreign_key: "source_project_id", class_name: MergeRequest
   has_many :issues,             dependent: :destroy, order: "state DESC, created_at DESC"
   has_many :milestones,         dependent: :destroy
   has_many :notes,              dependent: :destroy
@@ -312,8 +313,11 @@ class Project < ActiveRecord::Base
     branch_name = ref.gsub("refs/heads/", "")
     c_ids = self.repository.commits_between(oldrev, newrev).map(&:id)
 
-    # Update code for merge requests
+    # Update code for merge requests into project between project branches
     mrs = self.merge_requests.opened.by_branch(branch_name).all
+    # Update code for merge requests between project and project fork
+    mrs += self.fork_merge_requests.opened.by_branch(branch_name).all
+    
     mrs.each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked }
 
     # Close merge requests
-- 
GitLab


From 4f464781422bf002301f4eae1ee4edc73ccca672 Mon Sep 17 00:00:00 2001
From: Wes Gurney <wes.gurney@gmail.com>
Date: Wed, 9 Oct 2013 00:44:33 -0400
Subject: [PATCH 246/248] Rebased code

---
 config/gitlab.yml.example         | 6 +++---
 config/initializers/1_settings.rb | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index ebbcf760c6c..40ccd6e5412 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -69,10 +69,10 @@ production: &base
       wall: false
       snippets: false
       public: false
-
+ 
     ## Webhook settings
-    # Number of seconds to wait for HTTP response after sending webhook HTTP POST request (default: 10)
-    # webhook_timeout: 10
+    # webhook_timeout: 30  # default: 10 - Number of seconds to wait for HTTP response after sending webhook HTTP POST request
+
 
   ## External issues trackers
   issues_tracker:
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 1adb5c4e64d..9041170b829 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -71,7 +71,7 @@ Settings.gitlab['signup_enabled'] ||= false
 Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
 Settings.gitlab['issue_closing_pattern'] = '([Cc]loses|[Ff]ixes) #(\d+)' if Settings.gitlab['issue_closing_pattern'].nil?
 Settings.gitlab['default_projects_features'] ||= {}
-Settings.gitlab['webhook_timeout'] ||= 10   
+Settings.gitlab['webhook_timeout'] ||= 10
 Settings.gitlab.default_projects_features['issues']         = true if Settings.gitlab.default_projects_features['issues'].nil?
 Settings.gitlab.default_projects_features['merge_requests'] = true if Settings.gitlab.default_projects_features['merge_requests'].nil?
 Settings.gitlab.default_projects_features['wiki']           = true if Settings.gitlab.default_projects_features['wiki'].nil?
-- 
GitLab


From 3d1fdd93af877bb62129089245b8738a8a179ddc Mon Sep 17 00:00:00 2001
From: Wes Gurney <wes.gurney@gmail.com>
Date: Mon, 2 Sep 2013 21:20:39 -0400
Subject: [PATCH 247/248] Fixed default comments to make it clearer

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

diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 40ccd6e5412..0c66218eda5 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -71,7 +71,8 @@ production: &base
       public: false
  
     ## Webhook settings
-    # webhook_timeout: 30  # default: 10 - Number of seconds to wait for HTTP response after sending webhook HTTP POST request
+    # Number of seconds to wait for HTTP response after sending webhook HTTP POST request (default: 10)
+    # webhook_timeout: 10
 
 
   ## External issues trackers
-- 
GitLab


From 66990597a97124314611273349196bd94dbe93a5 Mon Sep 17 00:00:00 2001
From: Wes Gurney <wes.gurney@gmail.com>
Date: Fri, 4 Oct 2013 17:31:25 -0400
Subject: [PATCH 248/248] Cleaned comments

---
 config/initializers/1_settings.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 9041170b829..1adb5c4e64d 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -71,7 +71,7 @@ Settings.gitlab['signup_enabled'] ||= false
 Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
 Settings.gitlab['issue_closing_pattern'] = '([Cc]loses|[Ff]ixes) #(\d+)' if Settings.gitlab['issue_closing_pattern'].nil?
 Settings.gitlab['default_projects_features'] ||= {}
-Settings.gitlab['webhook_timeout'] ||= 10
+Settings.gitlab['webhook_timeout'] ||= 10   
 Settings.gitlab.default_projects_features['issues']         = true if Settings.gitlab.default_projects_features['issues'].nil?
 Settings.gitlab.default_projects_features['merge_requests'] = true if Settings.gitlab.default_projects_features['merge_requests'].nil?
 Settings.gitlab.default_projects_features['wiki']           = true if Settings.gitlab.default_projects_features['wiki'].nil?
-- 
GitLab