OSDN Git Service

Merge pull request #5308 from Popl7/parallel-diffs-side-by-side
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Tue, 26 Nov 2013 11:31:42 +0000 (03:31 -0800)
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Tue, 26 Nov 2013 11:31:42 +0000 (03:31 -0800)
diff view on commit with parallel diff view

96 files changed:
.travis.yml
CHANGELOG
Gemfile
Gemfile.lock
VERSION
app/assets/stylesheets/gitlab_bootstrap/common.scss
app/assets/stylesheets/gitlab_bootstrap/forms.scss
app/assets/stylesheets/sections/issues.scss
app/contexts/files/create_context.rb
app/contexts/files/delete_context.rb [new file with mode: 0644]
app/contexts/issues/list_context.rb
app/controllers/admin/dashboard_controller.rb
app/controllers/projects/blob_controller.rb
app/controllers/projects/issues_controller.rb
app/controllers/projects/new_tree_controller.rb
app/helpers/application_helper.rb
app/helpers/commits_helper.rb
app/helpers/events_helper.rb
app/helpers/icons_helper.rb [new file with mode: 0644]
app/helpers/issues_helper.rb
app/helpers/projects_helper.rb
app/models/assembla_service.rb [new file with mode: 0644]
app/models/event.rb
app/models/hipchat_service.rb
app/models/project.rb
app/services/project_transfer_service.rb
app/views/admin/dashboard/index.html.haml
app/views/devise/confirmations/new.html.erb [deleted file]
app/views/devise/confirmations/new.html.haml [new file with mode: 0644]
app/views/layouts/group.html.haml
app/views/layouts/profile.html.haml
app/views/layouts/project_settings.html.haml
app/views/projects/blob/_actions.html.haml
app/views/projects/blob/_remove.html.haml [new file with mode: 0644]
app/views/projects/blob/show.html.haml
app/views/projects/fork.html.haml
app/views/projects/issues/_head.html.haml
app/views/projects/issues/_issues.html.haml
app/views/projects/issues/index.html.haml
app/views/projects/services/_form.html.haml
app/views/projects/services/index.html.haml
app/views/projects/show.html.haml
app/views/snippets/_blob.html.haml
app/views/snippets/_form.html.haml
app/views/snippets/_snippet.html.haml
config/gitlab.yml.example
config/initializers/devise.rb
config/initializers/rack_attack.rb.example
config/routes.rb
doc/api/projects.md
doc/api/repositories.md
doc/development/architecture.md [new file with mode: 0644]
doc/install/installation.md
doc/install/requirements.md
doc/release/security.md
doc/update/5.1-to-5.4.md
doc/update/5.1-to-6.0.md
doc/update/5.3-to-5.4.md
doc/update/5.4-to-6.0.md
doc/update/6.0-to-6.1.md
doc/update/6.0-to-6.2.md
doc/update/6.1-to-6.2.md
doc/update/6.2-to-6.3.md [new file with mode: 0644]
doc/update/patch_versions.md
doc/update/ruby.md [new file with mode: 0644]
features/project/service.feature
features/steps/profile/profile.rb
features/steps/project/project_services.rb
features/steps/snippets/snippets.rb
lib/api/files.rb
lib/api/projects.rb
lib/backup/database.rb
lib/backup/manager.rb
lib/backup/repository.rb
lib/backup/uploads.rb
lib/gitlab/backend/grack_auth.rb
lib/gitlab/backend/shell.rb
lib/gitlab/satellite/files/delete_file_action.rb [new file with mode: 0644]
lib/gitlab/satellite/files/edit_file_action.rb
lib/gitlab/satellite/files/file_action.rb
lib/gitlab/satellite/files/new_file_action.rb
lib/gitlab/satellite/merge_action.rb
lib/gitlab/satellite/satellite.rb
lib/tasks/gitlab/check.rake
spec/contexts/issues/list_context_spec.rb [new file with mode: 0644]
spec/factories.rb
spec/features/issues_spec.rb
spec/helpers/gitlab_markdown_helper_spec.rb
spec/lib/auth_spec.rb
spec/models/assembla_service_spec.rb [new file with mode: 0644]
spec/models/user_spec.rb
spec/requests/api/files_spec.rb
spec/requests/api/projects_spec.rb
spec/requests/api/session_spec.rb
spec/support/login_helpers.rb
spec/support/test_env.rb

index f56311b..f36cae4 100644 (file)
@@ -16,6 +16,7 @@ rvm:
   - 2.0.0
 services:
   - mysql
+  - redis-server
 before_script:
   - "cp config/database.yml.$DB config/database.yml"
   - "cp config/gitlab.yml.example config/gitlab.yml"
index baddbbf..3c94361 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,10 @@
+v 6.4.0
+  - Added sorting to project issues page (Jason Blanchard)
+  - Assembla integration (Carlos Paramio)
+  - Fixed another 500 error with submodules
+  - UI: More compact issues page
+  - Minimal password length increased to 8 symbols
+
 v 6.3.0
   - API for adding gitlab-ci service
   - Init script now waits for pids to appear after (re)starting before reporting status (Rovanion Luckey)
@@ -9,6 +16,7 @@ v 6.3.0
   - Fixed issue with 500 error when group did not exist
   - Ability to leave project
   - You can create file in repo using UI
+  - You can remove file from repo using UI
   - API: dropped default_branch attribute from project during creation
   - Project default_branch is not stored in db any more. It takes from repo now.
   - Admin broadcast messages
@@ -16,8 +24,26 @@ v 6.3.0
   - Dont show last push widget if user removed this branch
   - Fix 500 error for repos with newline in file name
   - Extended html titles
-  - API: create/update repo files
+  - API: create/update/delete repo files
   - Admin can transfer project to any namespace
+  - API: projects/all for admin users
+  - Fix recent branches order
+
+v 6.2.4
+  - Security: Cast API private_token to string (CVE-2013-4580)
+  - Security: Require gitlab-shell 1.7.8 (CVE-2013-4581, CVE-2013-4582, CVE-2013-4583)
+  - Fix for Git SSH access for LDAP users
+
+v 6.2.3
+  - Security: More protection against CVE-2013-4489
+  - Security: Require gitlab-shell 1.7.4 (CVE-2013-4490, CVE-2013-4546)
+  - Fix sidekiq rake tasks
+
+v 6.2.2
+  - Security: Update gitlab_git (CVE-2013-4489)
+
+v 6.2.1
+  - Security: Fix issue with generated passwords for new users
 
 v 6.2.0
   - Public project pages are now visible to everyone (files, issues, wik, etc.)
@@ -104,6 +130,14 @@ v 6.0.0
   - Improved MR comments logic
   - Render readme file for projects in public area
 
+v 5.4.2
+  - Security: Cast API private_token to string (CVE-2013-4580)
+  - Security: Require gitlab-shell 1.7.8 (CVE-2013-4581, CVE-2013-4582, CVE-2013-4583)
+
+v 5.4.1
+  - Security: Fixes for CVE-2013-4489
+  - Security: Require gitlab-shell 1.7.4 (CVE-2013-4490, CVE-2013-4546)
+
 v 5.4.0
   - Ability to edit own comments
   - Documentation improvements
diff --git a/Gemfile b/Gemfile
index a543c5e..d9009db 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -24,7 +24,7 @@ gem 'omniauth-github'
 
 # Extracting information from a git repository
 # Provide access to Gitlab::Git library
-gem "gitlab_git", "~> 3.0.0.rc2"
+gem "gitlab_git", "~> 3.1.0"
 
 # Ruby/Rack Git Smart-HTTP Server Handler
 gem 'gitlab-grack', '~> 1.0.1', require: 'grack'
@@ -33,13 +33,13 @@ gem 'gitlab-grack', '~> 1.0.1', require: 'grack'
 gem 'gitlab_omniauth-ldap', '1.0.3', require: "omniauth-ldap"
 
 # Syntax highlighter
-gem "gitlab-pygments.rb", '~> 0.3.2', require: 'pygments.rb'
+gem "gitlab-pygments.rb", '~> 0.5.4', require: 'pygments.rb'
 
 # Git Wiki
-gem "gitlab-gollum-lib", "~> 1.0.1", require: 'gollum-lib'
+gem "gitlab-gollum-lib", "~> 1.0.2", require: 'gollum-lib'
 
 # Language detection
-gem "github-linguist", require: "linguist"
+gem "gitlab-linguist", "~> 2.9.6", require: "linguist"
 
 # API
 gem "grape", "~> 0.4.1"
@@ -135,7 +135,7 @@ group :assets do
   gem 'turbolinks'
   gem 'jquery-turbolinks'
 
-  gem 'chosen-rails',     "1.0.0"
+  gem 'chosen-rails',     "1.0.1"
   gem 'select2-rails'
   gem 'jquery-atwho-rails', "0.3.0"
   gem "jquery-rails",     "2.1.3"
index 4be72d2..5c64f8f 100644 (file)
@@ -61,12 +61,12 @@ GEM
     charlock_holmes (0.6.9.4)
     childprocess (0.3.9)
       ffi (~> 1.0, >= 1.0.11)
-    chosen-rails (1.0.0)
+    chosen-rails (1.0.1)
       coffee-rails (>= 3.2)
       compass-rails (>= 1.0)
       railties (>= 3.0)
       sass-rails (>= 3.2)
-    chunky_png (1.2.8)
+    chunky_png (1.2.9)
     cliver (0.2.1)
     code_analyzer (0.4.3)
       sexp_processor
@@ -77,7 +77,7 @@ GEM
     coffee-script (2.2.0)
       coffee-script-source
       execjs
-    coffee-script-source (1.6.2)
+    coffee-script-source (1.6.3)
     colored (1.2)
     colorize (0.5.8)
     compass (0.12.2)
@@ -119,8 +119,7 @@ GEM
     escape_utils (0.2.4)
     eventmachine (1.0.3)
     excon (0.13.4)
-    execjs (1.4.0)
-      multi_json (~> 1.0)
+    execjs (2.0.2)
     factory_girl (4.2.0)
       activesupport (>= 3.0.0)
     factory_girl_rails (4.2.1)
@@ -151,38 +150,39 @@ GEM
     fssm (0.2.10)
     gemoji (1.2.1)
     gherkin-ruby (0.3.0)
-    github-linguist (2.3.4)
-      charlock_holmes (~> 0.6.6)
-      escape_utils (~> 0.2.3)
-      mime-types (~> 1.19)
-      pygments.rb (>= 0.2.13)
-    github-markdown (0.5.3)
+    github-markdown (0.5.5)
     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)
+    gitlab-gollum-lib (1.0.2)
       github-markdown (~> 0.5.3)
       github-markup (>= 0.7.5, < 1.0.0)
-      gitlab-grit (>= 2.5.1)
+      gitlab-grit (~> 2.6.1)
+      gitlab-pygments.rb (~> 0.5.4)
       nokogiri (~> 1.5.9)
-      pygments.rb (~> 0.4.2)
       sanitize (~> 2.0.3)
       stringex (~> 1.5.1)
     gitlab-grack (1.0.1)
       rack (~> 1.4.1)
-    gitlab-grit (2.6.2)
+    gitlab-grit (2.6.3)
       charlock_holmes (~> 0.6.9)
       diff-lcs (~> 1.1)
       mime-types (~> 1.15)
       posix-spawn (~> 0.3.6)
-    gitlab-pygments.rb (0.3.2)
+    gitlab-linguist (2.9.6)
+      charlock_holmes (~> 0.6.6)
+      escape_utils (~> 0.2.4)
+      gitlab-pygments.rb (~> 0.5.4)
+      mime-types (~> 1.19)
+    gitlab-pygments.rb (0.5.4)
       posix-spawn (~> 0.3.6)
       yajl-ruby (~> 1.1.0)
-    gitlab_git (3.0.0.rc2)
+    gitlab_git (3.1.0)
       activesupport (~> 3.2.13)
-      github-linguist (~> 2.3.4)
       gitlab-grit (~> 2.6.1)
+      gitlab-linguist (~> 2.9.5)
+      gitlab-pygments.rb (~> 0.5.4)
     gitlab_meta (6.0)
     gitlab_omniauth-ldap (1.0.3)
       net-ldap (~> 0.3.1)
@@ -274,7 +274,7 @@ GEM
       mime-types (~> 1.16)
       treetop (~> 1.4.8)
     method_source (0.8.1)
-    mime-types (1.25)
+    mime-types (1.25.1)
     minitest (4.7.4)
     modernizr (2.6.2)
       sprockets (~> 2.0)
@@ -325,9 +325,6 @@ GEM
       coderay (~> 1.0.5)
       method_source (~> 0.8)
       slop (~> 3.4)
-    pygments.rb (0.4.2)
-      posix-spawn (~> 0.3.6)
-      yajl-ruby (~> 1.1.0)
     pyu-ruby-sasl (0.0.3.3)
     quiet_assets (1.0.2)
       railties (>= 3.1, < 5.0)
@@ -431,7 +428,7 @@ GEM
     safe_yaml (0.9.3)
     sanitize (2.0.3)
       nokogiri (>= 1.4.4, < 1.6)
-    sass (3.2.11)
+    sass (3.2.12)
     sass-rails (3.2.6)
       railties (~> 3.2.0)
       sass (>= 3.1.10)
@@ -559,7 +556,7 @@ DEPENDENCIES
   bootstrap-sass
   capybara
   carrierwave
-  chosen-rails (= 1.0.0)
+  chosen-rails (= 1.0.1)
   coffee-rails
   colored
   coveralls
@@ -575,13 +572,13 @@ DEPENDENCIES
   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-gollum-lib (~> 1.0.2)
   gitlab-grack (~> 1.0.1)
-  gitlab-pygments.rb (~> 0.3.2)
-  gitlab_git (~> 3.0.0.rc2)
+  gitlab-linguist (~> 2.9.6)
+  gitlab-pygments.rb (~> 0.5.4)
+  gitlab_git (~> 3.1.0)
   gitlab_meta (= 6.0)
   gitlab_omniauth-ldap (= 1.0.3)
   gon
diff --git a/VERSION b/VERSION
index 5a90325..26cb0a3 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-6.3.0.pre
+6.4.0.pre
index 82ec776..b5fd1fc 100644 (file)
@@ -1,5 +1,6 @@
 /** COLORS **/
 .cgray { color: gray }
+.clgray { color: #BBB }
 .cred { color: #D12F19 }
 .cgreen { color: #4a2 }
 .cblue { color: #29A }
@@ -93,6 +94,12 @@ pre.well-pre {
   font-size: 12px;
   font-style: normal;
   font-weight: normal;
+
+  &.label-gray {
+    background-color: #eee;
+    color: #999;
+    text-shadow: none;
+  }
 }
 
 /** Big Labels **/
@@ -120,3 +127,8 @@ pre.well-pre {
 .dropdown-menu > li > a {
   text-shadow: none;
 }
+
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+  background: #29b;
+}
index 3df5eba..d4da3fe 100644 (file)
@@ -3,6 +3,16 @@ form {
 
   label {
     @extend .control-label;
+
+    &.radio-label {
+      text-align: left;
+      width: 100%;
+      margin-left: 0;
+
+      input[type="radio"] {
+        margin-top: 1px !important;
+      }
+    }
   }
 }
 
index e384aeb..792bcef 100644 (file)
@@ -77,8 +77,8 @@ input.check_all_issues {
 @media (min-width: 800px)  { .issues_filters select { width: 160px; }  }
 @media (min-width: 1200px) { .issues_filters select { width: 220px; }  }
 
-@media (min-width: 800px)  { .issues_bulk_update select { width: 120px; }  }
-@media (min-width: 1200px) { .issues_bulk_update select { width: 160px; }  }
+@media (min-width: 800px)  { .issues_bulk_update .chosen-container { min-width: 120px; }  }
+@media (min-width: 1200px) { .issues_bulk_update .chosen-container { min-width: 160px; }  }
 
 .issues-holder {
   .issues_filters {
@@ -103,3 +103,19 @@ input.check_all_issues {
 .participants {
   margin-bottom: 10px;
 }
+
+.issues_bulk_update {
+  .chosen-container {
+    text-shadow: none;
+  }
+}
+
+.issue-search-form {
+  margin: 0;
+  height: 24px;
+
+  .issue_search {
+    border: 1px solid #DDD !important;
+    background-color: #f4f4f4;
+  }
+}
index ae73b11..1027313 100644 (file)
@@ -15,18 +15,13 @@ module Files
         return error("You can only create files if you are on top of a branch")
       end
 
-      file_name = params[:file_name]
+      file_name = File.basename(path)
+      file_path = path
 
       unless file_name =~ Gitlab::Regex.path_regex
         return error("Your changes could not be commited, because file name contains not allowed characters")
       end
 
-      file_path = if path.blank?
-                    file_name
-                  else
-                    File.join(path, file_name)
-                  end
-
       blob = repository.blob_at(ref, file_path)
 
       if blob
diff --git a/app/contexts/files/delete_context.rb b/app/contexts/files/delete_context.rb
new file mode 100644 (file)
index 0000000..b193772
--- /dev/null
@@ -0,0 +1,38 @@
+module Files
+  class DeleteContext < BaseContext
+    def execute
+      allowed = if project.protected_branch?(ref)
+                  can?(current_user, :push_code_to_protected_branches, project)
+                else
+                  can?(current_user, :push_code, project)
+                end
+
+      unless allowed
+        return error("You are not allowed to push into this branch")
+      end
+
+      unless repository.branch_names.include?(ref)
+        return error("You can only create files if you are on top of a branch")
+      end
+
+      blob = repository.blob_at(ref, path)
+
+      unless blob
+        return error("You can only edit text files")
+      end
+
+      delete_file_action = Gitlab::Satellite::DeleteFileAction.new(current_user, project, ref, path)
+
+      deleted_successfully = delete_file_action.commit!(
+        nil,
+        params[:commit_message]
+      )
+
+      if deleted_successfully
+        success
+      else
+        error("Your changes could not be commited, because the file has been changed")
+      end
+    end
+  end
+end
index da2eed0..fd27356 100644 (file)
@@ -29,8 +29,26 @@ module Issues
       if params[:milestone_id].present?
         @issues = @issues.where(milestone_id: (params[:milestone_id] == '0' ? nil : params[:milestone_id]))
       end
+      
+      # Sort by :sort param
+      @issues = sort(@issues, params[:sort])
 
       @issues
     end
+
+    private
+
+    def sort(issues, condition)
+      case condition
+      when 'newest' then issues.except(:order).order('created_at DESC')
+      when 'oldest' then issues.except(:order).order('created_at ASC')
+      when 'recently_updated' then issues.except(:order).order('updated_at DESC')
+      when 'last_updated' then issues.except(:order).order('updated_at ASC')
+      when 'milestone_due_soon' then issues.except(:order).joins(:milestone).order("milestones.due_date ASC")
+      when 'milestone_due_later' then issues.except(:order).joins(:milestone).order("milestones.due_date DESC")
+      else issues
+      end
+    end
+
   end
 end
index 3c80b65..be19139 100644 (file)
@@ -2,5 +2,6 @@ class Admin::DashboardController < Admin::ApplicationController
   def index
     @projects = Project.order("created_at DESC").limit(10)
     @users = User.order("created_at DESC").limit(10)
+    @groups = Group.order("created_at DESC").limit(10)
   end
 end
index ba46625..087c163 100644 (file)
@@ -7,9 +7,30 @@ class Projects::BlobController < Projects::ApplicationController
   before_filter :authorize_code_access!
   before_filter :require_non_empty_project
 
+  before_filter :blob
+
   def show
-    @blob = @repository.blob_at(@commit.id, @path)
+  end
+
+  def destroy
+    result = Files::DeleteContext.new(@project, current_user, params, @ref, @path).execute
+
+    if result[:status] == :success
+      flash[:notice] = "Your changes have been successfully commited"
+      redirect_to project_tree_path(@project, @ref)
+    else
+      flash[:alert] = result[:error]
+      render :show
+    end
+  end
+
+  private
+
+  def blob
+    @blob ||= @repository.blob_at(@commit.id, @path)
+
+    return not_found! unless @blob
 
-    not_found! unless @blob
+    @blob
   end
 end
index e8f845b..e03d54c 100644 (file)
@@ -23,6 +23,9 @@ class Projects::IssuesController < Projects::ApplicationController
     assignee_id, milestone_id = params[:assignee_id], params[:milestone_id]
     @assignee = @project.team.find(assignee_id) if assignee_id.present? && !assignee_id.to_i.zero?
     @milestone = @project.milestones.find(milestone_id) if milestone_id.present? && !milestone_id.to_i.zero?
+    sort_param = params[:sort] || 'newest'
+    @sort = sort_param.humanize unless sort_param.empty?
+
 
     respond_to do |format|
       format.html # index.html.erb
index 9f9e019..d6d474c 100644 (file)
@@ -5,11 +5,12 @@ class Projects::NewTreeController < Projects::BaseTreeController
   end
 
   def update
-    result = Files::CreateContext.new(@project, current_user, params, @ref, @path).execute
+    file_path = File.join(@path, File.basename(params[:file_name]))
+    result = Files::CreateContext.new(@project, current_user, params, @ref, file_path).execute
 
     if result[:status] == :success
       flash[:notice] = "Your changes have been successfully commited"
-      redirect_to project_blob_path(@project, File.join(@id, params[:file_name]))
+      redirect_to project_blob_path(@project, File.join(@ref, file_path))
     else
       flash[:alert] = result[:error]
       render :show
index d8cbd8f..04fda02 100644 (file)
@@ -187,14 +187,6 @@ module ApplicationHelper
     Gitlab.config.extra
   end
 
-  def public_icon
-    content_tag :i, nil, class: 'icon-globe cblue'
-  end
-
-  def private_icon
-    content_tag :i, nil, class: 'icon-lock cgreen'
-  end
-
   def search_placeholder
     if @project && @project.persisted?
       "Search in this project"
index 654788a..663369e 100644 (file)
@@ -129,7 +129,9 @@ module CommitsHelper
             source_name
           end
 
-    user = User.where('name like ? or email like ?', source_name, source_email).first
+    # Prefer email match over name match
+    user = User.where(email: source_email).first
+    user ||= User.where(name: source_name).first
 
     options = {
       class: "commit-#{options[:source]}-link has_tooltip",
index 4aeb657..d3671ef 100644 (file)
@@ -102,15 +102,11 @@ module EventsHelper
         end
       elsif event.note_project_snippet?
         link_to(project_snippet_path(event.project, event.note_target)) do
-          content_tag :strong do
-            "#{event.note_target_type} ##{truncate event.note_target_id}"
-          end
+          "#{event.note_target_type} ##{truncate event.note_target_id}"
         end
       else
         link_to event_note_target_path(event) do
-          content_tag :strong do
-            "#{event.note_target_type} ##{truncate event.note_target_iid}"
-          end
+          "#{event.note_target_type} ##{truncate event.note_target_iid}"
         end
       end
     elsif event.wall_note?
diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb
new file mode 100644 (file)
index 0000000..e4dfc23
--- /dev/null
@@ -0,0 +1,17 @@
+module IconsHelper
+  def boolean_to_icon(value)
+    if value.to_s == "true"
+      content_tag :i, nil, class: 'icon-ok cgreen'
+    else
+      content_tag :i, nil, class: 'icon-off clgray'
+    end
+  end
+
+  def public_icon
+    content_tag :i, nil, class: 'icon-globe cblue'
+  end
+
+  def private_icon
+    content_tag :i, nil, class: 'icon-lock cgreen'
+  end
+end
index 2221583..56b776c 100644 (file)
@@ -68,4 +68,12 @@ module IssuesHelper
       false
     end
   end
+
+  def bulk_update_milestone_options
+    options_for_select(["None (backlog)", nil]) + options_from_collection_for_select(project_active_milestones, "id", "title", params[:milestone_id])
+  end
+
+  def bulk_update_assignee_options
+    options_for_select(["None (unassigned)", nil]) + options_from_collection_for_select(@project.team.members, "id", "name", params[:assignee_id])
+  end
 end
index ee0e681..6b6903c 100644 (file)
@@ -70,6 +70,8 @@ module ProjectsHelper
       scope: params[:scope],
       label_name: params[:label_name],
       milestone_id: params[:milestone_id],
+      assignee_id: params[:assignee_id],
+      sort: params[:sort],
     }
 
     options = exist_opts.merge(options)
diff --git a/app/models/assembla_service.rb b/app/models/assembla_service.rb
new file mode 100644 (file)
index 0000000..66ecf39
--- /dev/null
@@ -0,0 +1,45 @@
+# == 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)
+#  subdomain   :string(255)
+#  room        :string(255)
+#
+
+class AssemblaService < Service
+  include HTTParty
+
+  validates :token, presence: true, if: :activated?
+
+  def title
+    'Assembla'
+  end
+
+  def description
+    'Project Management Software (Source Commits Endpoint)'
+  end
+
+  def to_param
+    'assembla'
+  end
+
+  def fields
+    [
+      { type: 'text', name: 'token', placeholder: '' }
+    ]
+  end
+
+  def execute(push)
+    url = "https://atlas.assembla.com/spaces/ouposp/github_tool?secret_key=#{token}"
+    AssemblaService.post(url, body: { payload: push }.to_json, headers: { 'Content-Type' => 'application/json' })
+  end
+end
index f78f127..771c628 100644 (file)
@@ -223,7 +223,7 @@ class Event < ActiveRecord::Base
 
   # Max 20 commits from push DESC
   def commits
-    @commits ||= data[:commits].reverse
+    @commits ||= (data[:commits] || []).reverse
   end
 
   def commits_count
index 7fec5c4..ea2169f 100644 (file)
@@ -25,7 +25,7 @@ class HipchatService < Service
   end
 
   def description
-    'Simple web-based real-time group chat'
+    'Private group chat and IM'
   end
 
   def to_param
index e255f13..eab7c14 100644 (file)
@@ -50,6 +50,7 @@ class Project < ActiveRecord::Base
   has_one :pivotaltracker_service, dependent: :destroy
   has_one :hipchat_service, dependent: :destroy
   has_one :flowdock_service, dependent: :destroy
+  has_one :assembla_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
 
@@ -224,7 +225,7 @@ class Project < ActiveRecord::Base
   end
 
   def available_services_names
-    %w(gitlab_ci campfire hipchat pivotaltracker flowdock)
+    %w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla)
   end
 
   def gitlab_ci?
index 7150c1c..7055ef3 100644 (file)
@@ -18,6 +18,10 @@ class ProjectTransferService
         raise TransferError.new("Project with same path in target namespace already exists")
       end
 
+      # Remove old satellite
+      project.satellite.destroy
+
+      # Apply new namespace id
       project.namespace = new_namespace
       project.save!
 
@@ -29,8 +33,8 @@ class ProjectTransferService
       # Move wiki repo also if present
       gitlab_shell.mv_repository("#{old_path}.wiki", "#{new_path}.wiki")
 
-      # create satellite repo
-      project.ensure_satellite_exists
+      # Create a new satellite (reload project from DB)
+      Project.find(project.id).ensure_satellite_exists
 
       # clear project cached events
       project.reset_events_cache
index 3064763..9cd9096 100644 (file)
           ago
 
   .span4
+    %h4 Latest groups
+    %hr
+    - @groups.each do |group|
+      %p
+        = link_to [:admin, group] do
+          = group.name
+        %span.light.pull-right
+          = time_ago_in_words group.created_at
+          ago
+
+%br
+.row
+  .span4
     %h4 Stats
     %hr
     %p
       Milestones
       %span.light.pull-right
         = Milestone.count
+  .span4
+    %h4
+      Features
+    %hr
+    %p
+      Sign up
+      %span.light.pull-right
+        = boolean_to_icon gitlab_config.signup_enabled
+    %p
+      LDAP
+      %span.light.pull-right
+        = boolean_to_icon Gitlab.config.ldap.enabled
+    %p
+      Gravatar
+      %span.light.pull-right
+        = boolean_to_icon Gitlab.config.gravatar.enabled
+    %p
+      OmniAuth
+      %span.light.pull-right
+        = boolean_to_icon Gitlab.config.omniauth.enabled
+  .span4
+    %h4 Components
+    %hr
+    %p
+      GitLab
+      %span.pull-right
+        = Gitlab::VERSION
+    %p
+      GitLab Shell
+      %span.pull-right
+        = Gitlab::Shell.new.version
diff --git a/app/views/devise/confirmations/new.html.erb b/app/views/devise/confirmations/new.html.erb
deleted file mode 100644 (file)
index adc9b67..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<h2>Resend confirmation instructions</h2>
-
-<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
-  <%= devise_error_messages! %>
-
-  <div><%= f.label :email %><br />
-  <%= f.email_field :email %></div>
-
-  <div><%= f.submit "Resend confirmation instructions" %></div>
-<% end %>
-
-<%= render partial: "devise/shared/links" %>
diff --git a/app/views/devise/confirmations/new.html.haml b/app/views/devise/confirmations/new.html.haml
new file mode 100644 (file)
index 0000000..387ec76
--- /dev/null
@@ -0,0 +1,8 @@
+.login-box
+  %h3.page-title Resend confirmation instructions
+  = form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f|
+    = devise_error_messages!
+    = f.email_field :email, placeholder: 'Email'
+    %div= f.submit "Resend confirmation instructions", class: 'btn btn-success'
+  %hr
+  = link_to "Sign in", new_session_path(resource_name)
index 7462121..b546a9f 100644 (file)
@@ -2,6 +2,7 @@
 %html{ lang: "en"}
   = render "layouts/head", title: group_head_title
   %body{class: "#{app_theme} application", :'data-page' => body_data_page}
+    = render "layouts/broadcast"
     = render "layouts/head_panel", title: "group: #{@group.name}"
     = render "layouts/flash"
     %nav.main-nav
index 30a0532..7284963 100644 (file)
@@ -2,6 +2,7 @@
 %html{ lang: "en"}
   = render "layouts/head", title: "Profile"
   %body{class: "#{app_theme} profile", :'data-page' => body_data_page}
+    = render "layouts/broadcast"
     = render "layouts/head_panel", title: "Profile"
     = render "layouts/flash"
     %nav.main-nav
index ea739da..6a10d6c 100644 (file)
@@ -2,6 +2,7 @@
 %html{ lang: "en"}
   = render "layouts/head", title: @project.name_with_namespace
   %body{class: "#{app_theme} project", :'data-page' => body_data_page, :'data-project-id' => @project.id }
+    = render "layouts/broadcast"
     = render "layouts/head_panel", title: project_title(@project)
     = render "layouts/init_auto_complete"
     = render "layouts/flash"
index f6cc62e..2f82bfe 100644 (file)
@@ -4,7 +4,7 @@
     - if allowed_tree_edit?
       = link_to "edit", project_edit_tree_path(@project, @id), class: "btn btn-small"
     - else
-      %span.btn.btn-small.disabled Edit
+      %span.btn.btn-small.disabled edit
   = link_to "raw", project_raw_path(@project, @id), class: "btn btn-small", target: "_blank"
   -# only show normal/blame view links for text files
   - if @blob.text?
@@ -13,3 +13,7 @@
     - else
       = link_to "blame", project_blame_path(@project, @id), class: "btn btn-small" unless @blob.empty?
   = link_to "history", project_commits_path(@project, @id), class: "btn btn-small"
+
+  - if allowed_tree_edit?
+    = link_to '#modal-remove-blob', class: "remove-blob btn btn-small btn-remove", "data-toggle" => "modal" do
+      remove
diff --git a/app/views/projects/blob/_remove.html.haml b/app/views/projects/blob/_remove.html.haml
new file mode 100644 (file)
index 0000000..1c09733
--- /dev/null
@@ -0,0 +1,19 @@
+%div#modal-remove-blob.modal.hide
+  .modal-header
+    %a.close{href: "#", "data-dismiss" => "modal"} Ã—
+    %h3.page-title Remove #{@blob.name}
+    %p.light
+      From branch
+      %strong= @ref
+
+  .modal-body
+    = form_tag project_blob_path(@project, @id), method: :delete do
+      .control-group.commit_message-group
+        = label_tag 'commit_message', class: "control-label" do
+          Commit message
+        .controls
+          = text_area_tag 'commit_message', params[:commit_message], placeholder: "Removed this file because...", required: true, rows: 3
+      .control-group
+        .controls
+          = submit_tag 'Remove file', class: 'btn btn-remove'
+          = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal"
index d96595b..56220e5 100644 (file)
@@ -2,3 +2,6 @@
   = render 'shared/ref_switcher', destination: 'blob', path: @path
 %div#tree-holder.tree-holder
   = render 'blob', blob: @blob
+
+- if allowed_tree_edit?
+  = render 'projects/blob/remove'
index a1c109e..227fde8 100644 (file)
@@ -3,9 +3,9 @@
     %i.icon-code-fork
     Fork Error!
   %p
-    You are trying to fork
+    You tried to fork
     = link_to_project @project
-    but it fails due to next reason:
+    but it failed for the following reason:
 
 
   - if @forked_project && @forked_project.errors.any?
index 438cc02..8ae9ba5 100644 (file)
@@ -1,11 +1,29 @@
 %ul.nav.nav-tabs
   = nav_link(controller: :issues) do
-    = link_to 'Browse Issues', project_issues_path(@project), class: "tab"
+    = link_to project_issues_path(@project), class: "tab" do
+      Browse Issues
+      - if current_controller?(:issues)
+        %span.badge.issue_counter #{@issues.total_count}
   = nav_link(controller: :milestones) do
     = link_to 'Milestones', project_milestones_path(@project), class: "tab"
   = nav_link(controller: :labels) do
     = link_to 'Labels', project_labels_path(@project), class: "tab"
-  - if current_user
+
+  - if current_controller?(:issues)
+    - if current_user
+      %li
+        = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
+          %i.icon-rss
+
     %li.pull-right
-      = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
-        %i.icon-rss
+      .pull-right
+        - if can? current_user, :write_issue, @project
+          = link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-new pull-right", title: "New Issue", id: "new_issue_link" do
+            %i.icon-plus
+            New Issue
+        = form_tag project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: 'pull-right issue-search-form'  do
+          = hidden_field_tag :status, params[:status], id: 'search_status'
+          = hidden_field_tag :assignee_id, params[:assignee_id], id: 'search_assignee_id'
+          = hidden_field_tag :milestone_id, params[:milestone_id], id: 'search_milestone_id'
+          = hidden_field_tag :label_name, params[:label_name], id: 'search_label_name'
+          = search_field_tag :issue_search, nil, { placeholder: 'Filter by title or description', class: 'input-xpadding issue_search input-xlarge append-right-10 search-text-input' }
index 427d653..0cde7ac 100644 (file)
@@ -6,8 +6,8 @@
         = form_tag bulk_update_project_issues_path(@project), method: :post  do
           %span Update selected issues with &nbsp;
           = select_tag('update[status]', options_for_select(['open', 'closed']), prompt: "Status")
-          = select_tag('update[assignee_id]', options_from_collection_for_select(@project.team.members, "id", "name", params[:assignee_id]), prompt: "Assignee")
-          = select_tag('update[milestone_id]', options_from_collection_for_select(project_active_milestones, "id", "title", params[:milestone_id]), prompt: "Milestone")
+          = select_tag('update[assignee_id]', bulk_update_assignee_options, prompt: "Assignee")
+          = select_tag('update[milestone_id]', bulk_update_milestone_options, prompt: "Milestone")
           = hidden_field_tag 'update[issues_ids]', []
           = hidden_field_tag :status, params[:status]
           = button_tag "Save", class: "btn update_selected_issues btn-small btn-save"
                   %strong= milestone.title
                   %small.light= milestone.expires_at
 
+        .dropdown.inline.prepend-left-10
+          %a.dropdown-toggle.btn.btn-small{href: '#', "data-toggle" => "dropdown"}
+            %span.light sort:
+            - if @sort.present?
+              = @sort
+            - else
+              Newest
+            %b.caret
+          %ul.dropdown-menu
+            %li
+              = link_to project_filter_path(sort: 'newest') do
+                Newest
+              = link_to project_filter_path(sort: 'oldest') do
+                Oldest
+              = link_to project_filter_path(sort: 'recently_updated') do
+                Recently updated
+              = link_to project_filter_path(sort: 'last_updated') do
+                Last updated
+              = link_to project_filter_path(sort: 'milestone_due_soon') do
+                Milestone due soon
+              = link_to project_filter_path(sort: 'milestone_due_later') do
+                Milestone due later
+
 
   %ul.well-list.issues-list
     = render @issues
index 81594b4..3694798 100644 (file)
@@ -1,21 +1,4 @@
 = render "head"
-.issues_content
-  %h3.page-title
-    Issues
-    %span (<span class=issue_counter>#{@issues.total_count}</span>)
-    .pull-right
-      .span6
-        - if can? current_user, :write_issue, @project
-          = link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-new pull-right", title: "New Issue", id: "new_issue_link" do
-            %i.icon-plus
-            New Issue
-        = form_tag project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: 'pull-right'  do
-          = hidden_field_tag :status, params[:status], id: 'search_status'
-          = hidden_field_tag :assignee_id, params[:assignee_id], id: 'search_assignee_id'
-          = hidden_field_tag :milestone_id, params[:milestone_id], id: 'search_milestone_id'
-          = hidden_field_tag :label_name, params[:label_name], id: 'search_label_name'
-          = search_field_tag :issue_search, nil, { placeholder: 'Filter by title or description', class: 'input-xpadding issue_search input-xlarge append-right-10 search-text-input' }
-
 .row
   .span3
     = render 'shared/project_filter', project_entities_path: project_issues_path(@project)
index a099193..202bf32 100644 (file)
@@ -1,11 +1,6 @@
 %h3.page-title
-  - if @service.activated?
-    %span.cgreen
-      %i.icon-circle
-  - else
-    %span.cgray
-      %i.icon-circle-blank
   = @service.title
+  = boolean_to_icon @service.activated?
 
 %p= @service.description
 
index 82b85a1..190aa69 100644 (file)
@@ -6,12 +6,8 @@
   - @services.each do |service|
     %li
       %h4
-        - if service.activated?
-          %span.cgreen
-            %i.icon-circle
-        - else
-          %span.cgray
-            %i.icon-circle-blank
         = link_to edit_project_service_path(@project, service.to_param) do
           = service.title
+        .pull-right
+          = boolean_to_icon service.activated?
       %p= service.description
index 5e5b316..1f4b583 100644 (file)
@@ -1,6 +1,6 @@
 .project-home-panel
   .row
-    .span4
+    .span5
       %h4.project-home-title
         = @project.name_with_namespace
         - if @project.public
@@ -8,7 +8,7 @@
         - else
           %span.public-label Private
 
-    .span8
+    .span7
       .project-home-dropdown
         = render "dropdown"
       .form-horizontal
index c2e0d97..dc856f8 100644 (file)
@@ -8,9 +8,18 @@
           = link_to "Edit", edit_snippet_path(@snippet), class: "btn btn-tiny", title: 'Edit Snippet'
           = link_to "Delete", snippet_path(@snippet), method: :delete, confirm: "Are you sure?", class: "btn btn-tiny", title: 'Delete Snippet'
         = link_to "Raw", raw_snippet_path(@snippet), class: "btn btn-tiny", target: "_blank"
-  .file-content.code
-    - unless @snippet.content.empty?
-      %div{class: user_color_scheme_class}
-        = raw @snippet.colorize(formatter: :gitlab)
+  - unless @snippet.content.empty?
+    - if gitlab_markdown?(@snippet.file_name)
+      .file-content.wiki
+        = preserve do
+          = markdown(@snippet.data)
+    - elsif markup?(@snippet.file_name)
+      .file-content.wiki
+        = raw GitHub::Markup.render(@snippet.file_name, @snippet.data)
     - else
+      .file-content.code
+        %div{class: user_color_scheme_class}
+          = raw @snippet.colorize(formatter: :gitlab)
+  - else
+    .file-content.code
       %p.nothing_here_message Empty file
index e77550e..517c81f 100644 (file)
       = f.label :title
       .controls= f.text_field :title, placeholder: "Example Snippet", class: 'input-xlarge', required: true
     .control-group
-      = f.label "Private?"
+      = f.label "Access"
       .controls
-        = f.check_box :private, {class: ''}
+        = f.label :private_true, class: 'radio-label' do
+          = f.radio_button :private, true
+          %span
+            %strong Private
+            (only you can see this snippet)
+        %br
+        = f.label :private_false, class: 'radio-label' do
+          = f.radio_button :private, false
+          %span
+            %strong Public
+            (GitLab users can can see this snippet)
+
     .control-group
       .file-editor
         = f.label :file_name, "File"
       - else
         = f.submit 'Save', class: "btn-save btn"
 
-      = link_to "Cancel", snippets_path(@project), class: "btn btn-cancel"
       - unless @snippet.new_record?
-        .pull-right= link_to 'Destroy', snippet_path(@snippet), confirm: 'Removed snippet cannot be restored! Are you sure?', method: :delete, class: "btn pull-right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
+        .pull-right.prepend-left-20
+          = link_to 'Remove', snippet_path(@snippet), confirm: 'Removed snippet cannot be restored! Are you sure?', method: :delete, class: "btn btn-remove delete-snippet", id: "destroy_snippet_#{@snippet.id}"
+      = link_to "Cancel", snippets_path(@project), class: "btn btn-cancel"
 
 
 :javascript
index 8514bc3..a50d813 100644 (file)
@@ -3,7 +3,7 @@
     = link_to reliable_snippet_path(snippet) do
       = truncate(snippet.title, length: 60)
       - if snippet.private?
-        %span.label.label-success
+        %span.label.label-gray
           %i.icon-lock
           private
     %span.cgray.monospace.tiny.pull-right
index bd018dc..759d743 100644 (file)
@@ -57,7 +57,7 @@ production: &base
 
     ## Automatic issue closing
     # 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.
+    # This happens 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]lose[sd]|[Ff]ixe[sd]) +#\d+
 
index b7cb808..dcf829c 100644 (file)
@@ -101,7 +101,7 @@ Devise.setup do |config|
 
   # ==> Configuration for :validatable
   # Range for password length. Default is 6..128.
-  config.password_length = 6..128
+  config.password_length = 8..128
 
   # Email regex used to validate email formats. It simply asserts that
   # an one (and only one) @ exists in the given string. This is mainly
index c6d3605..1d10a53 100644 (file)
@@ -5,8 +5,13 @@
 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}/api/#{API::API.version}/session.json",
+  "#{Rails.application.config.relative_url_root}/api/#{API::API.version}/session",
   "#{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?
+
+unless Rails.env.test?
+  Rack::Attack.throttle('protected paths', limit: 10, period: 60.seconds) do |req|
+    req.ip if paths_to_be_protected.include?(req.path) && req.post?
+  end
 end
index 06e8fdd..d89fc20 100644 (file)
@@ -173,7 +173,7 @@ Gitlab::Application.routes.draw do
     end
 
     scope module: :projects do
-      resources :blob,      only: [:show], constraints: {id: /.+/}
+      resources :blob,      only: [:show, :destroy], constraints: {id: /.+/}
       resources :raw,       only: [:show], constraints: {id: /.+/}
       resources :tree,      only: [:show], constraints: {id: /.+/, format: /(html|js)/ }
       resources :edit_tree, only: [:show, :update], constraints: {id: /.+/}, path: 'edit'
index d4d883e..9b5d62a 100644 (file)
@@ -2,7 +2,7 @@
 
 ### List projects
 
-Get a list of projects owned by the authenticated user.
+Get a list of projects accessible by the authenticated user.
 
 ```
 GET /projects
@@ -82,6 +82,22 @@ GET /projects
 ```
 
 
+#### List owned projects
+
+Get a list of projects owned by the authenticated user.
+
+```
+GET /projects/owned
+```
+
+#### List ALL projects
+
+Get a list of all GitLab projects (admin only).
+
+```
+GET /projects/all
+```
+
 ### Get single project
 
 Get a specific project, identified by project ID or NAMESPACE/PROJECT_NAME , which is owned by the authentication user.
index 9ec6ba7..af7b82c 100644 (file)
@@ -379,8 +379,7 @@ POST /projects/:id/repository/files
 
 Parameters:
 
-+ `file_name` (required) - The name of new file. Ex. class.rb
-+ `file_path` (optional) - The path to new file. Ex. lib/
++ `file_path` (optional) - Full path to new file. Ex. lib/class.rb
 + `branch_name` (required) - The name of branch
 + `content` (required) - File content
 + `commit_message` (required) - Commit message
@@ -397,3 +396,15 @@ Parameters:
 + `branch_name` (required) - The name of branch
 + `content` (required) - New file content
 + `commit_message` (required) - Commit message
+
+## Delete existing file in repository
+
+```
+DELETE /projects/:id/repository/files
+```
+
+Parameters:
+
++ `file_path` (required) - Full path to file. Ex. lib/class.rb
++ `branch_name` (required) - The name of branch
++ `commit_message` (required) - Commit message
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
new file mode 100644 (file)
index 0000000..db22f0b
--- /dev/null
@@ -0,0 +1,23 @@
+# GitLab project architecture
+
+GitLab project consists of two parts: GitLab and GitLab shell.
+
+## GitLab
+
+Web application with background jobs workers. 
+Provides you with UI and most of functionality.
+For some operations like repo creation - uses GitLab shell.
+
+Uses: 
+ * Ruby as main language for application code and most libraries. 
+ * [Rails](http://rubyonrails.org/) web framework as main framework for application.
+ * Mysql or postgres as main databases. Used for persistent data storage(users, project, issues etc). 
+ * Redis database. Used for cache and exchange data between some components.
+ * Python2 because of [pygments](http://pygments.org/) as code syntax highlighter.
+
+## GitLab shell
+
+Command line ruby application. Used by GitLab through shell commands.
+It provides interface to all kind of manipulations with repositories and ssh keys.
+Full list of commands you can find in README of GitLab shell repo.
+Works on pure ruby and do not require any additional software.
index ce8a7b2..19233eb 100644 (file)
@@ -118,8 +118,8 @@ Remove the old Ruby 1.8 if present
 Download Ruby and compile it:
 
     mkdir /tmp/ruby && cd /tmp/ruby
-    curl --progress ftp://ftp.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-p247.tar.gz | tar xz
-    cd ruby-2.0.0-p247
+    curl --progress ftp://ftp.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-p353.tar.gz | tar xz
+    cd ruby-2.0.0-p353
     ./configure --disable-install-rdoc
     make
     sudo make install
@@ -149,7 +149,7 @@ GitLab Shell is an ssh access and repository management software developed speci
     cd gitlab-shell
 
     # switch to right version
-    sudo -u git -H git checkout v1.7.8
+    sudo -u git -H git checkout v1.7.9
 
     sudo -u git -H cp config.yml.example config.yml
 
@@ -180,10 +180,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-2-stable
+    sudo -u git -H git checkout 6-3-stable
 
 **Note:**
-You can change `6-2-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
+You can change `6-3-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
 
 ## Configure it
 
index a9dd348..e9c95ba 100644 (file)
@@ -1,40 +1,45 @@
 # Operating Systems
 
-## Linux
-
 GitLab is developed for the Linux operating system.
 
-GitLab officially supports (recent versions of) these Linux distributions:
+## GitLab officially supports
 
 - Ubuntu Linux
 - Debian/GNU Linux
 
-It should also work on (though they are not officially supported):
+## GitLab.com offers paid support for
 
-- Arch
+- Red Hat Enterprise Linux (RHEL)
 - CentOS
+- Oracle Linux
+
+## Not officially supported
+
+- Arch Linux
 - Fedora
 - Gentoo
-- RHEL
 
-## Other Unix Systems
+On the above distributions it is pretty easy to install GitLab yourself.
+
+## Unsupported Unix Systems
 
-There is nothing that prevents GitLab from running on other Unix operating
-systems. This means you may get it to work on systems running FreeBSD or OS X.
-**If you want to try, please proceed with caution!**
+There is nothing that prevents GitLab from running on other Unix operating systems.
+This means you may get it to work on systems running FreeBSD or OS X.
+If you want to do this, please be aware it could be a lot of work.
+Please consider using a virtual machine to run GitLab.
 
-## Windows
+## Other operating systems such as Windows
 
-GitLab does **not** run on Windows and we have no plans of supporting it in the
-near future. Please consider using a virtual machine to run GitLab.
+GitLab does **not** run on Windows and we have no plans of supporting it in the near future.
+Please consider using a virtual machine to run GitLab.
 
 
-# Rubies
+# Ruby versions
 
-GitLab requires Ruby (MRI) 1.9.3 and several Gems with native components.
-While it is generally possible to use other Rubies (like
-[JRuby](http://jruby.org/) or [Rubinius](http://rubini.us/)) it might require
-some work on your part.
+GitLab requires Ruby (MRI) 1.9.3 or 2.0+.
+While it is generally possible to use other Rubies
+(like [JRuby](http://jruby.org/) or [Rubinius](http://rubini.us/))
+it might require some work since GitLab uses several Gems that have native extensions.
 
 
 # Hardware requirements
index 68857ea..a77cbae 100644 (file)
@@ -13,27 +13,33 @@ Please report suspected security vulnerabilities in private to support@gitlab.co
 
 1. Verify that the issue can be repoduced
 1. Acknowledge the issue to the researcher that disclosed it
-1. Fix the issue on a feature branch, do this on the private dev.gitlab.org server and update the VERSION and CHANGELOG
+1. Fix the issue on a feature branch, do this on the private GitLab development server and update the VERSION and CHANGELOG in this branch
 1. Consider creating and testing workarounds
 1. Create feature branches for the blog posts on GitLab.org and GitLab.com and link them from the code branch
-1. Merge the code feature branch
-1. Create a git tag vX.X.X for CE and another one for EE
+1. Merge the code feature branch into master
+1. Cherry-pick the code into the latest stable branch
+1. Create a git tag vX.X.X for CE and another patch release for EE
 1. Push the code and the tags to all the CE and EE repositories
+1. Apply the patch to GitLab Cloud and the private GitLab development server
 1. Merge and publish the blog posts
 1. Send tweets about the release from @gitlabhq and @git_lab
 1. Send out an email to the subscribers mailing list on MailChimp
 1. Send out an email to [the community google mailing list](https://groups.google.com/forum/#!forum/gitlabhq)
 1. Send out an email to [the GitLab newsletter list](http://gitlab.us5.list-manage.com/subscribe?u=498dccd07cf3e9482bee33ba4&id=98a9a4992c)
-1. Post a signed copy of our announcement to [oss-security](http://www.openwall.com/lists/oss-security/) and request a CVE number
+1. Post a signed copy of our complete announcement to [oss-security](http://www.openwall.com/lists/oss-security/) and request a CVE number
 1. Add the security researcher to the [Security Researcher Acknowledgments list](http://www.gitlab.com/vulnerability-acknowledgements/)
 1. Thank the security researcher in an email for their cooperation
-1. Update the blogposts when we receive a CVE number
+1. Update the blogpost and the CHANGELOG when we receive the CVE number
+
+The timing of the code merge into master should be coordinated in advance.
+After the merge we strive to publish the announcements within 60 minutes.
 
 ## Blog post template
 
 XXX Security Advisory for GitLab
 
 A recently discovered critical vulnerability in GitLab allows [unauthenticated API access|remote code execution|unauthorized access to repositories|XXX|PICKSOMETHING]. All users should update GitLab and gitlab-shell immediately.
+We [have|haven't|XXX|PICKSOMETHING|] heard of this vulnerability being actively exploited.
 
 ### Version affected
 
index a845191..3061507 100644 (file)
@@ -31,7 +31,7 @@ sudo -u git -H git checkout 5-4-stable # Latest version of 5-4-stable addresses
 ```bash
 cd /home/git/gitlab-shell
 sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.8 # Addresses multiple critical security vulnerabilities
+sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulnerabilities
 ```
 
 ### 4. Install libs, migrations, etc.
index 793688b..53a3c64 100644 (file)
@@ -47,7 +47,7 @@ sudo -u git -H git checkout 6-0-stable
 ```bash
 cd /home/git/gitlab-shell
 sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.8
+sudo -u git -H git checkout v1.7.9
 ```
 
 ### 4. Install additional packages
index 2e2e4ca..11c0f7c 100644 (file)
@@ -30,7 +30,7 @@ sudo -u git -H git checkout 5-4-stable # Latest version of 5-4-stable addresses
 ```bash
 cd /home/git/gitlab-shell
 sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.8 # Addresses multiple critical security vulnerabilities
+sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulnerabilities
 ```
 
 ### 4. Install libs, migrations, etc.
index dcf58a1..8990f8d 100644 (file)
@@ -47,7 +47,7 @@ sudo -u git -H git checkout 6-0-stable
 ```bash
 cd /home/git/gitlab-shell
 sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.8
+sudo -u git -H git checkout v1.7.9
 ```
 
 ### 4. Install additional packages
index 314d18b..f02f054 100644 (file)
@@ -39,7 +39,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.8
+sudo -u git -H git checkout v1.7.9
 ```
 
 ### 4. Install libs, migrations, etc.
index dbab684..03d7e96 100644 (file)
@@ -47,7 +47,7 @@ sudo apt-get install logrotate
 ```bash
 cd /home/git/gitlab-shell
 sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.8 # Addresses multiple critical security vulnerabilities
+sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulnerabilities
 ```
 
 ### 5. Install libs, migrations, etc.
@@ -74,7 +74,7 @@ sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
 TIP: to see what changed in gitlab.yml.example in this release use next command: 
 
 ```
-git diff 6-1-stable:config/gitlab.yml.example 6-2-stable:config/gitlab.yml.example
+git diff 6-0-stable:config/gitlab.yml.example 6-2-stable:config/gitlab.yml.example
 ```
 
 * 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.
index 1ce17f4..767ad80 100644 (file)
@@ -32,7 +32,7 @@ sudo -u git -H git checkout 6-2-stable # Latest version of 6-2-stable addresses
 ```bash
 cd /home/git/gitlab-shell
 sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.8 # Addresses multiple critical security vulnerabilities
+sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulnerabilities
 ```
 
 ### 4. Install additional packages
diff --git a/doc/update/6.2-to-6.3.md b/doc/update/6.2-to-6.3.md
new file mode 100644 (file)
index 0000000..d1c570c
--- /dev/null
@@ -0,0 +1,120 @@
+# From 6.2 to 6.3
+
+## Requires version: 6.1 or 6.2
+
+### 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 bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 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-3-stable
+```
+
+### 3. Update gitlab-shell (and its config)
+
+```bash
+cd /home/git/gitlab-shell
+sudo -u git -H git fetch
+sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulnerabilities
+```
+
+The Gitlab-shell config changed recently, so check for config file changes and make `/home/git/gitlab-shell/config.yml` the same as https://github.com/gitlabhq/gitlab-shell/blob/master/config.yml.example
+
+### 4. Install additional packages
+
+```bash
+# Add support for lograte for better log file handling
+sudo apt-get install logrotate
+```
+
+### 5. 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 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
+```
+
+### 6. Update config files
+
+TIP: to see what changed in gitlab.yml.example in this release use next command: 
+
+```
+git diff 6-2-stable:config/gitlab.yml.example 6-3-stable:config/gitlab.yml.example
+git diff 6-1-stable:config/gitlab.yml.example 6-3-stable:config/gitlab.yml.example # if you upgrading from 6-1
+```
+
+* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/6-3-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-3-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
+```
+* Set up logrotate
+
+```bash
+sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
+```
+
+### 7. Update Init script
+
+```bash
+sudo rm /etc/init.d/gitlab
+sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/6-3-stable/lib/support/init.d/gitlab
+sudo chmod +x /etc/init.d/gitlab
+```
+
+### 8. Start application
+
+    sudo service gitlab start
+    sudo service nginx restart
+
+### 9. 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.2)
+
+### 1. Revert the code to the previous version
+Follow the [`upgrade guide from 6.1 to 6.2`](6.1-to-6.2.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 bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
index 4d128a3..61542db 100644 (file)
@@ -26,7 +26,7 @@ sudo -u git -H git pull origin 6-2-stable
 ```bash
 cd /home/git/gitlab-shell
 sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.8
+sudo -u git -H git checkout v1.7.9
 ```
 
 ### 4. Install libs, migrations, etc.
diff --git a/doc/update/ruby.md b/doc/update/ruby.md
new file mode 100644 (file)
index 0000000..c1c85e1
--- /dev/null
@@ -0,0 +1,53 @@
+# Updating Ruby from source
+
+This guide explains how to update Ruby in case you installed it from source according to the instructions in https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md#2-ruby .
+
+### 1. Look for Ruby versions
+This guide will only update `/usr/local/bin/ruby`. You can see which Ruby binaries are installed on your system by running:
+
+```bash
+ls -l $(which -a ruby)
+```
+
+### 2. Stop GitLab
+
+```bash
+sudo service gitlab stop
+```
+
+### 3. Install or update dependencies
+Here we are assuming you are using Debian/Ubuntu.
+
+```bash
+sudo apt-get install build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl
+```
+
+### 4. Download, compile and install Ruby
+Find the latest stable version of Ruby 1.9 or 2.0 at https://www.ruby-lang.org/en/downloads/ . We recommend at least 2.0.0p353, which is patched against [CVE-2013-4164](https://www.ruby-lang.org/en/news/2013/11/22/heap-overflow-in-floating-point-parsing-cve-2013-4164/).
+
+```bash
+cd /tmp
+curl --progress http://cache.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-p353.tar.gz | tar xz
+cd ruby-2.0.0-p353
+./configure --disable-install-rdoc
+make
+sudo make install # overwrite the existing Ruby in /usr/local/bin
+```
+
+### 5. Reinstall GitLab gem bundle
+Just to be sure we will reinstall the gems used by GitLab. Note that the `bundle install` command [depends on your choice of database](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md#install-gems).
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H rm -rf vendor/bundle  # remove existing Gem bundle
+sudo -u git -H bundle install --deployment --without development test postgres aws # Assuming MySQL
+```
+
+### 6. Start GitLab
+We are now ready to restart GitLab.
+
+```bash
+sudo service gitlab start
+```
+
+### Done
index 4805d2b..f8684f3 100644 (file)
@@ -30,3 +30,9 @@ Feature: Project Services
     And I click Flowdock service link
     And I fill Flowdock settings
     Then I should see Flowdock service settings saved
+
+  Scenario: Activate Assembla service
+    When I visit project "Shop" services page
+    And I click Assembla service link
+    And I fill Assembla settings
+    Then I should see Assembla service settings saved
\ No newline at end of file
index 753e2c1..9d091e9 100644 (file)
@@ -33,24 +33,24 @@ class Profile < Spinach::FeatureSteps
 
   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"
+      fill_in "user_password", with: "22233344"
+      fill_in "user_password_confirmation", with: "22233344"
       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"
+      fill_in "user_current_password", with: "12345678"
+      fill_in "user_password", with: "22233344"
+      fill_in "user_password_confirmation", with: "22233344"
       click_button "Save"
     end
   end
 
   step 'I unsuccessfully change my password' do
     within '.update-password' do
-      fill_in "user_current_password", with: "123456"
+      fill_in "user_current_password", with: "12345678"
       fill_in "user_password", with: "password"
       fill_in "user_password_confirmation", with: "confirmation"
       click_button "Save"
index 70eafc8..2f24809 100644 (file)
@@ -12,6 +12,7 @@ class ProjectServices < Spinach::FeatureSteps
     page.should have_content 'Campfire'
     page.should have_content 'Hipchat'
     page.should have_content 'GitLab CI'
+    page.should have_content 'Assembla'
   end
 
   And 'I click gitlab-ci service link' do
@@ -72,4 +73,18 @@ class ProjectServices < Spinach::FeatureSteps
   Then 'I should see Flowdock service settings saved' do
     find_field('Token').value.should == 'verySecret'
   end
+
+  And 'I click Assembla service link' do
+    click_link 'Assembla'
+  end
+
+  And 'I fill Assembla settings' do
+    check 'Active'
+    fill_in 'Token', with: 'verySecret'
+    click_button 'Save'
+  end
+
+  Then 'I should see Assembla service settings saved' do
+    find_field('Token').value.should == 'verySecret'
+  end
 end
index bbdf5b9..1aea01f 100644 (file)
@@ -19,7 +19,7 @@ class SnippetsFeature < Spinach::FeatureSteps
   end
 
   And 'I click link "Destroy"' do
-    click_link "Destroy"
+    click_link "Remove"
   end
 
   And 'I submit new snippet "Personal snippet three"' do
@@ -46,7 +46,7 @@ class SnippetsFeature < Spinach::FeatureSteps
   end
 
   And 'I uncheck "Private" checkbox' do
-    find(:xpath, "//input[@id='personal_snippet_private']").set true
+    choose "Public"
     click_button "Save"
   end
 
index e467b0f..6a5419a 100644 (file)
@@ -8,8 +8,7 @@ module API
       # Create new file in repository
       #
       # Parameters:
-      #   file_name (required) - The name of new file. Ex. class.rb
-      #   file_path (optional) - The path to new file. Ex. lib/
+      #   file_path (optional) - The path to new file. Ex. lib/class.rb
       #   branch_name (required) - The name of branch
       #   content (required) - File content
       #   commit_message (required) - Commit message
@@ -18,8 +17,8 @@ module API
       #   POST /projects/:id/repository/files
       #
       post ":id/repository/files" do
-        required_attributes! [:file_name, :branch_name, :content, :commit_message]
-        attrs = attributes_for_keys [:file_name, :file_path, :branch_name, :content, :commit_message]
+        required_attributes! [:file_path, :branch_name, :content, :commit_message]
+        attrs = attributes_for_keys [:file_path, :branch_name, :content, :commit_message]
         branch_name = attrs.delete(:branch_name)
         file_path = attrs.delete(:file_path)
         result = ::Files::CreateContext.new(user_project, current_user, attrs, branch_name, file_path).execute
@@ -28,7 +27,6 @@ module API
           status(201)
 
           {
-            file_name: attrs[:file_name],
             file_path: file_path,
             branch_name: branch_name
           }
@@ -40,8 +38,7 @@ module API
       # Update existing file in repository
       #
       # Parameters:
-      #   file_name (required) - The name of new file. Ex. class.rb
-      #   file_path (optional) - The path to new file. Ex. lib/
+      #   file_path (optional) - The path to file. Ex. lib/class.rb
       #   branch_name (required) - The name of branch
       #   content (required) - File content
       #   commit_message (required) - Commit message
@@ -67,7 +64,36 @@ module API
           render_api_error!(result[:error], 400)
         end
       end
+
+      # Delete existing file in repository
+      #
+      # Parameters:
+      #   file_path (optional) - The path to file. Ex. lib/class.rb
+      #   branch_name (required) - The name of branch
+      #   content (required) - File content
+      #   commit_message (required) - Commit message
+      #
+      # Example Request:
+      #   DELETE /projects/:id/repository/files
+      #
+      delete ":id/repository/files" do
+        required_attributes! [:file_path, :branch_name, :commit_message]
+        attrs = attributes_for_keys [:file_path, :branch_name, :commit_message]
+        branch_name = attrs.delete(:branch_name)
+        file_path = attrs.delete(:file_path)
+        result = ::Files::DeleteContext.new(user_project, current_user, attrs, branch_name, file_path).execute
+
+        if result[:status] == :success
+          status(200)
+
+          {
+            file_path: file_path,
+            branch_name: branch_name
+          }
+        else
+          render_api_error!(result[:error], 400)
+        end
+      end
     end
   end
 end
-
index 4256057..b927e63 100644 (file)
@@ -31,6 +31,16 @@ module API
         present @projects, with: Entities::Project
       end
 
+      # Get all projects for admin user
+      #
+      # Example Request:
+      #   GET /projects/all
+      get '/all' do
+        authenticated_as_admin!
+        @projects = paginate Project
+        present @projects, with: Entities::Project
+      end
+
       # Get a single project
       #
       # Parameters:
index c4fb2e2..7af7140 100644 (file)
@@ -13,20 +13,20 @@ module Backup
     def dump
       case config["adapter"]
       when /^mysql/ then
-        system("mysqldump #{mysql_args} #{config['database']} > #{db_file_name}")
+        system('mysqldump', *mysql_args, config['database'], out: db_file_name)
       when "postgresql" then
         pg_env
-        system("pg_dump #{config['database']} > #{db_file_name}")
+        system('pg_dump', config['database'], out: db_file_name)
       end
     end
 
     def restore
       case config["adapter"]
       when /^mysql/ then
-        system("mysql #{mysql_args} #{config['database']} < #{db_file_name}")
+        system('mysql', *mysql_args, config['database'], in: db_file_name)
       when "postgresql" then
         pg_env
-        system("psql #{config['database']} -f #{db_file_name}")
+        system('psql', config['database'], '-f', db_file_name)
       end
     end
 
@@ -45,7 +45,7 @@ module Backup
         'encoding'  => '--default-character-set',
         'password'  => '--password'
       }
-      args.map { |opt, arg| "#{arg}='#{config[opt]}'" if config[opt] }.compact.join(' ')
+      args.map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }.compact
     end
 
     def pg_env
index 258a0fb..efaefa4 100644 (file)
@@ -1,5 +1,7 @@
 module Backup
   class Manager
+    BACKUP_CONTENTS = %w{repositories/ db/ uploads/ backup_information.yml}
+
     def pack
       # saving additional informations
       s = {}
@@ -16,7 +18,7 @@ module Backup
 
       # create archive
       print "Creating backup archive: #{s[:backup_created_at].to_i}_gitlab_backup.tar ... "
-      if Kernel.system("tar -cf #{s[:backup_created_at].to_i}_gitlab_backup.tar repositories/ db/ uploads/ backup_information.yml")
+      if Kernel.system('tar', '-cf', "#{s[:backup_created_at].to_i}_gitlab_backup.tar", *BACKUP_CONTENTS)
         puts "done".green
       else
         puts "failed".red
@@ -25,7 +27,7 @@ module Backup
 
     def cleanup
       print "Deleting tmp directories ... "
-      if Kernel.system("rm -rf repositories/ db/ uploads/ backup_information.yml")
+      if Kernel.system('rm', '-rf', *BACKUP_CONTENTS)
         puts "done".green
       else
         puts "failed".red
@@ -44,7 +46,7 @@ module Backup
         file_list.map! { |f| $1.to_i if f =~ /(\d+)_gitlab_backup.tar/ }
         file_list.sort.each do |timestamp|
           if Time.at(timestamp) < (Time.now - keep_time)
-            if system("rm #{timestamp}_gitlab_backup.tar")
+            if Kernel.system(*%W(rm #{timestamp}_gitlab_backup.tar))
               removed += 1
             end
           end
@@ -75,7 +77,7 @@ module Backup
       end
 
       print "Unpacking backup ... "
-      unless Kernel.system("tar -xf #{tar_file}")
+      unless Kernel.system(*%W(tar -xf #{tar_file}))
         puts "failed".red
         exit 1
       else
index 252201f..20fd5ba 100644 (file)
@@ -18,7 +18,7 @@ module Backup
         # Create namespace dir if missing
         FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.path)) if project.namespace
 
-        if system("cd #{path_to_repo(project)} > /dev/null 2>&1 && git bundle create #{path_to_bundle(project)} --all > /dev/null 2>&1")
+        if system(*%W(git --git-dir=#{path_to_repo(project)} bundle create #{path_to_bundle(project)} --all), silent)
           puts "[DONE]".green
         else
           puts "[FAILED]".red
@@ -30,7 +30,7 @@ module Backup
           print " * #{wiki.path_with_namespace} ... "
           if wiki.empty?
             puts " [SKIPPED]".cyan
-          elsif system("cd #{path_to_repo(wiki)} > /dev/null 2>&1 && git bundle create #{path_to_bundle(wiki)} --all > /dev/null 2>&1")
+          elsif system(*%W(git --git-dir=#{path_to_repo(wiki)} bundle create #{path_to_bundle(wiki)} --all), silent)
             puts " [DONE]".green
           else
             puts " [FAILED]".red
@@ -53,7 +53,7 @@ module Backup
 
         project.namespace.ensure_dir_exist if project.namespace
 
-        if system("git clone --bare #{path_to_bundle(project)} #{path_to_repo(project)} > /dev/null 2>&1")
+        if system(*%W(git clone --bare #{path_to_bundle(project)} #{path_to_repo(project)}), silent)
           puts "[DONE]".green
         else
           puts "[FAILED]".red
@@ -63,7 +63,7 @@ module Backup
 
         if File.exists?(path_to_bundle(wiki))
           print " * #{wiki.path_with_namespace} ... "
-          if system("git clone --bare #{path_to_bundle(wiki)} #{path_to_repo(wiki)} > /dev/null 2>&1")
+          if system(*%W(git clone --bare #{path_to_bundle(wiki)} #{path_to_repo(wiki)}), silent)
             puts " [DONE]".green
           else
             puts " [FAILED]".red
@@ -73,7 +73,7 @@ module Backup
 
       print 'Put GitLab hooks in repositories dirs'.yellow
       gitlab_shell_user_home = File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}")
-      if system("#{gitlab_shell_user_home}/gitlab-shell/support/rewrite-hooks.sh #{Gitlab.config.gitlab_shell.repos_path}")
+      if system("#{gitlab_shell_user_home}/gitlab-shell/support/rewrite-hooks.sh", Gitlab.config.gitlab_shell.repos_path)
         puts " [DONE]".green
       else
         puts " [FAILED]".red
@@ -103,5 +103,9 @@ module Backup
       FileUtils.rm_rf(backup_repos_path)
       FileUtils.mkdir_p(backup_repos_path)
     end
+
+    def silent
+      {err: '/dev/null', out: '/dev/null'}
+    end
   end
 end
index 462d3f1..e79da7e 100644 (file)
@@ -19,7 +19,7 @@ module Backup
 
       FileUtils.cp_r(backup_uploads_dir, app_uploads_dir)
     end
-    
+
     def backup_existing_uploads_dir
       if File.exists?(app_uploads_dir)
         FileUtils.mv(app_uploads_dir, Rails.root.join('public', "uploads.#{Time.now.to_i}"))
index e09cf31..e234949 100644 (file)
@@ -82,13 +82,17 @@ module Grack
       when 'git-upload-pack'
         project.public || can?(user, :download_code, project)
       when'git-receive-pack'
-        action = if project.protected_branch?(ref)
-                   :push_code_to_protected_branches
-                 else
-                   :push_code
-                 end
+        refs.each do |ref|
+          action = if project.protected_branch?(ref)
+                     :push_code_to_protected_branches
+                   else
+                     :push_code
+                   end
+
+          return false unless can?(user, action, project)
+        end
 
-        can?(user, action, project)
+        true
       else
         false
       end
@@ -108,11 +112,11 @@ module Grack
       @project ||= project_by_path(@request.path_info)
     end
 
-    def ref
-      @ref ||= parse_ref
+    def refs
+      @refs ||= parse_refs
     end
 
-    def parse_ref
+    def parse_refs
       input = if @env["HTTP_CONTENT_ENCODING"] =~ /gzip/
                 Zlib::GzipReader.new(@request.body).read
               else
@@ -121,7 +125,15 @@ module Grack
 
       # Need to reset seek point
       @request.body.rewind
-      /refs\/heads\/([\/\w\.-]+)/n.match(input.force_encoding('ascii-8bit')).to_a.last
+
+      # Parse refs
+      refs = input.force_encoding('ascii-8bit').scan(/refs\/heads\/([\/\w\.-]+)/n).flatten.compact
+
+      # Cleanup grabare from refs
+      # if push to multiple branches
+      refs.map do |ref|
+        ref.gsub(/00.*/, "")
+      end
     end
   end
 end
index c819ce5..5020fa1 100644 (file)
@@ -196,6 +196,15 @@ module Gitlab
       Gitlab.config.gitlab_shell.ssh_path_prefix + "#{path}.git"
     end
 
+    # Return GitLab shell version
+    def version
+      gitlab_shell_version_file = "#{gitlab_shell_user_home}/gitlab-shell/VERSION"
+
+      if File.readable?(gitlab_shell_version_file)
+        File.read(gitlab_shell_version_file)
+      end
+    end
+
     protected
 
     def gitlab_shell_user_home
diff --git a/lib/gitlab/satellite/files/delete_file_action.rb b/lib/gitlab/satellite/files/delete_file_action.rb
new file mode 100644 (file)
index 0000000..3046299
--- /dev/null
@@ -0,0 +1,50 @@
+require_relative 'file_action'
+
+module Gitlab
+  module Satellite
+    class DeleteFileAction < FileAction
+      # Deletes file and creates a new commit for it
+      #
+      # Returns false if committing the change fails
+      # Returns false if pushing from the satellite to bare repo failed or was rejected
+      # Returns true otherwise
+      def commit!(content, commit_message)
+        in_locked_and_timed_satellite do |repo|
+          prepare_satellite!(repo)
+
+          # create target branch in satellite at the corresponding commit from bare repo
+          repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
+
+          # update the file in the satellite's working dir
+          file_path_in_satellite = File.join(repo.working_dir, file_path)
+
+          # Prevent relative links
+          unless safe_path?(file_path_in_satellite)
+            Gitlab::GitLogger.error("FileAction: Relative path not allowed")
+            return false
+          end
+
+          File.delete(file_path_in_satellite)
+
+          # add removed file
+          repo.remove(file_path_in_satellite)
+
+          # commit the changes
+          # will raise CommandFailed when commit fails
+          repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
+
+
+          # push commit back to bare repo
+          # will raise CommandFailed when push fails
+          repo.git.push({raise: true, timeout: true}, :origin, ref)
+
+          # everything worked
+          true
+        end
+      rescue Grit::Git::CommandFailed => ex
+        Gitlab::GitLogger.error(ex.message)
+        false
+      end
+    end
+  end
+end
index 3747c6a..f410ecb 100644 (file)
@@ -8,17 +8,24 @@ module Gitlab
       #
       # Returns false if the ref has been updated while editing the file
       # Returns false if committing the change fails
-      # Returns false if pushing from the satellite to Gitolite failed or was rejected
+      # Returns false if pushing from the satellite to bare repo failed or was rejected
       # Returns true otherwise
       def commit!(content, commit_message)
         in_locked_and_timed_satellite do |repo|
           prepare_satellite!(repo)
 
-          # create target branch in satellite at the corresponding commit from Gitolite
+          # create target branch in satellite at the corresponding commit from bare repo
           repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
 
           # update the file in the satellite's working dir
           file_path_in_satellite = File.join(repo.working_dir, file_path)
+
+          # Prevent relative links
+          unless safe_path?(file_path_in_satellite)
+            Gitlab::GitLogger.error("FileAction: Relative path not allowed")
+            return false
+          end
+
           File.open(file_path_in_satellite, 'w') { |f| f.write(content) }
 
           # commit the changes
@@ -26,7 +33,7 @@ module Gitlab
           repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
 
 
-          # push commit back to Gitolite
+          # push commit back to bare repo
           # will raise CommandFailed when push fails
           repo.git.push({raise: true, timeout: true}, :origin, ref)
 
index 7c08e29..0f7afde 100644 (file)
@@ -8,6 +8,10 @@ module Gitlab
         @file_path = file_path
         @ref = ref
       end
+
+      def safe_path?(path)
+        File.absolute_path(path) == path
+      end
     end
   end
 end
index 97b1980..57d101f 100644 (file)
@@ -7,17 +7,28 @@ module Gitlab
       #
       # Returns false if the ref has been updated while editing the file
       # Returns false if committing the change fails
-      # Returns false if pushing from the satellite to Gitolite failed or was rejected
+      # Returns false if pushing from the satellite to bare repo failed or was rejected
       # Returns true otherwise
       def commit!(content, commit_message)
         in_locked_and_timed_satellite do |repo|
           prepare_satellite!(repo)
 
-          # create target branch in satellite at the corresponding commit from Gitolite
+          # create target branch in satellite at the corresponding commit from bare repo
           repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
 
-          # update the file in the satellite's working dir
           file_path_in_satellite = File.join(repo.working_dir, file_path)
+          dir_name_in_satellite = File.dirname(file_path_in_satellite)
+
+          # Prevent relative links
+          unless safe_path?(file_path_in_satellite)
+            Gitlab::GitLogger.error("FileAction: Relative path not allowed")
+            return false
+          end
+
+          # Create dir if not exists
+          FileUtils.mkdir_p(dir_name_in_satellite)
+
+          # Write file
           File.open(file_path_in_satellite, 'w') { |f| f.write(content) }
 
           # add new file
@@ -28,7 +39,7 @@ module Gitlab
           repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
 
 
-          # push commit back to Gitolite
+          # push commit back to bare repo
           # will raise CommandFailed when push fails
           repo.git.push({raise: true, timeout: true}, :origin, ref)
 
index d74d419..54afd6a 100644 (file)
@@ -28,7 +28,7 @@ module Gitlab
         in_locked_and_timed_satellite do |merge_repo|
           prepare_satellite!(merge_repo)
           if merge_in_satellite!(merge_repo)
-            # push merge back to Gitolite
+            # push merge back to bare repo
             # will raise CommandFailed when push fails
             merge_repo.git.push(default_options, :origin, merge_request.target_branch)
             # remove source branch
index 6cb7814..353c302 100644 (file)
@@ -123,7 +123,7 @@ module Gitlab
         remotes.each { |name| repo.git.remote(default_options,'rm', name)}
       end
 
-      # Updates the satellite from Gitolite
+      # Updates the satellite from bare repo
       #
       # Note: this will only update remote branches (i.e. origin/*)
       def update_from_source!
index 009806f..f2349ca 100644 (file)
@@ -611,10 +611,7 @@ namespace :gitlab do
     end
 
     def gitlab_shell_version
-      gitlab_shell_version_file = "#{gitlab_shell_user_home}/gitlab-shell/VERSION"
-      if File.readable?(gitlab_shell_version_file)
-        File.read(gitlab_shell_version_file)
-      end
+      Gitlab::Shell.new.version
     end
 
     def has_gitlab_shell3?
@@ -736,7 +733,7 @@ namespace :gitlab do
   end
 
   def check_gitlab_shell
-    required_version = Gitlab::VersionInfo.new(1, 7, 8)
+    required_version = Gitlab::VersionInfo.new(1, 7, 9)
     current_version = Gitlab::VersionInfo.parse(gitlab_shell_version)
 
     print "GitLab Shell version >= #{required_version} ? ... "
diff --git a/spec/contexts/issues/list_context_spec.rb b/spec/contexts/issues/list_context_spec.rb
new file mode 100644 (file)
index 0000000..63f2f38
--- /dev/null
@@ -0,0 +1,77 @@
+require 'spec_helper'
+
+describe Issues::ListContext do
+
+  let(:user) { create(:user) }
+  let(:project) { create(:project, creator: user) }
+  
+  titles = ['foo','bar','baz']
+  titles.each_with_index do |title, index|
+    let!(title.to_sym) { create(:issue, title: title, project: project, created_at: Time.now - (index * 60)) }
+  end
+
+  describe 'sorting' do
+
+    it 'sorts by newest' do
+      params = {:sort => 'newest'}
+
+      issues = Issues::ListContext.new(project, user, params).execute
+      issues.first.should eq foo
+    end
+
+    it 'sorts by oldest' do
+      params = {:sort => 'oldest'}
+
+      issues = Issues::ListContext.new(project, user, params).execute
+      issues.first.should eq baz
+    end
+
+    it 'sorts by recently updated' do
+      params = {:sort => 'recently_updated'}
+      baz.updated_at = Time.now + 10
+      baz.save
+
+      issues = Issues::ListContext.new(project, user, params).execute
+      issues.first.should eq baz
+    end
+
+    it 'sorts by least recently updated' do
+      params = {:sort => 'last_updated'}
+      bar.updated_at = Time.now - 10
+      bar.save
+
+      issues = Issues::ListContext.new(project, user, params).execute
+      issues.first.should eq bar
+    end
+
+    describe 'sorting by milestone' do
+
+      let(:newer_due_milestone) { create(:milestone, :due_date => '2013-12-11') }
+      let(:later_due_milestone) { create(:milestone, :due_date => '2013-12-12') }
+
+      before :each do
+        foo.milestone = newer_due_milestone
+        foo.save
+        bar.milestone = later_due_milestone
+        bar.save
+      end
+
+      it 'sorts by most recently due milestone' do
+        params = {:sort => 'milestone_due_soon'}
+
+        issues = Issues::ListContext.new(project, user, params).execute
+        issues.first.should eq foo
+
+      end
+
+      it 'sorts by least recently due milestone' do
+        params = {:sort => 'milestone_due_later'}
+
+        issues = Issues::ListContext.new(project, user, params).execute
+        issues.first.should eq bar
+      end
+
+    end
+  end
+
+end
index 3b0e305..daf8417 100644 (file)
@@ -15,7 +15,7 @@ FactoryGirl.define do
     email { Faker::Internet.email }
     name
     sequence(:username) { |n| "#{Faker::Internet.user_name}#{n}" }
-    password "123456"
+    password "12345678"
     password_confirmation { password }
     confirmed_at { Time.now }
     confirmation_token { nil }
index 8cb9849..5b1a14a 100644 (file)
@@ -95,4 +95,87 @@ describe "Issues" do
       page.should have_content 'gitlab'
     end
   end
+
+  describe 'filter issue' do
+    titles = ['foo','bar','baz']
+    titles.each_with_index do |title, index|
+      let!(title.to_sym) { create(:issue, title: title, project: project, created_at: Time.now - (index * 60)) }
+    end
+    let(:newer_due_milestone) { create(:milestone, :due_date => '2013-12-11') }
+    let(:later_due_milestone) { create(:milestone, :due_date => '2013-12-12') }
+
+    it 'sorts by newest' do
+      visit project_issues_path(project, sort: 'newest')
+      
+      page.should have_selector("ul.issues-list li:first-child", :text => 'foo')
+      page.should have_selector("ul.issues-list li:last-child", :text => 'baz')
+    end
+
+    it 'sorts by oldest' do
+      visit project_issues_path(project, sort: 'oldest')
+
+      page.should have_selector("ul.issues-list li:first-child", :text => 'baz')
+      page.should have_selector("ul.issues-list li:last-child", :text => 'foo')
+    end
+
+    it 'sorts by most recently updated' do
+      baz.updated_at = Time.now + 100
+      baz.save
+      visit project_issues_path(project, sort: 'recently_updated')
+
+      page.should have_selector("ul.issues-list li:first-child", :text => 'baz')
+    end
+
+    it 'sorts by least recently updated' do
+      baz.updated_at = Time.now - 100
+      baz.save
+      visit project_issues_path(project, sort: 'last_updated')
+
+      page.should have_selector("ul.issues-list li:first-child", :text => 'baz')
+    end
+
+    describe 'sorting by milestone' do
+      
+      before :each do 
+        foo.milestone = newer_due_milestone
+        foo.save
+        bar.milestone = later_due_milestone
+        bar.save
+      end
+
+      it 'sorts by recently due milestone' do
+        visit project_issues_path(project, sort: 'milestone_due_soon')
+
+        page.should have_selector("ul.issues-list li:first-child", :text => 'foo')
+      end
+
+      it 'sorts by least recently due milestone' do
+        visit project_issues_path(project, sort: 'milestone_due_later')
+
+        page.should have_selector("ul.issues-list li:first-child", :text => 'bar')
+      end
+    end
+
+    describe 'combine filter and sort' do
+
+      let(:user2) { create(:user) }
+
+      before :each do
+        foo.assignee = user2
+        foo.save
+        bar.assignee = user2
+        bar.save
+      end
+
+      it 'sorts with a filter applied' do
+        visit project_issues_path(project, sort: 'oldest', assignee_id: user2.id)
+
+        page.should have_selector("ul.issues-list li:first-child", :text => 'bar')
+        page.should have_selector("ul.issues-list li:last-child", :text => 'foo')
+        page.should_not have_content 'baz'
+
+      end
+    end
+  end
+
 end
index a0bbc02..6afd4b5 100644 (file)
@@ -378,9 +378,10 @@ describe GitlabMarkdownHelper do
     it "should leave code blocks untouched" do
       helper.stub(:user_color_scheme_class).and_return(:white)
 
-      helper.markdown("\n    some code from $#{snippet.id}\n    here too\n").should include("<div class=\"white\"><div class=\"highlight\"><pre><span class=\"n\">some</span> <span class=\"n\">code</span> <span class=\"n\">from</span> $#{snippet.id}\n<span class=\"n\">here</span> <span class=\"n\">too</span>\n</pre></div></div>")
+      target_html = "<div class=\"white\"><div class=\"highlight\"><pre><span class=\"n\">some</span> <span class=\"n\">code</span> <span class=\"n\">from</span> <span class=\"err\">$</span><span class=\"mi\">#{snippet.id}</span>"
 
-      helper.markdown("\n```\nsome code from $#{snippet.id}\nhere too\n```\n").should include("<div class=\"white\"><div class=\"highlight\"><pre><span class=\"n\">some</span> <span class=\"n\">code</span> <span class=\"n\">from</span> $#{snippet.id}\n<span class=\"n\">here</span> <span class=\"n\">too</span>\n</pre></div></div>")
+      helper.markdown("\n    some code from $#{snippet.id}\n    here too\n").should include(target_html)
+      helper.markdown("\n```\nsome code from $#{snippet.id}\nhere too\n```\n").should include(target_html)
     end
 
     it "should leave inline code untouched" do
index e05fde9..073b811 100644 (file)
@@ -8,21 +8,21 @@ describe Gitlab::Auth do
       @user = create(
         :user,
         username: 'john',
-        password: '888777',
-        password_confirmation: '888777'
+        password: '88877711',
+        password_confirmation: '88877711'
       )
     end
 
     it "should find user by valid login/password" do
-      gl_auth.find('john', '888777').should == @user
+      gl_auth.find('john', '88877711').should == @user
     end
 
     it "should not find user with invalid password" do
-      gl_auth.find('john', 'invalid').should_not == @user
+      gl_auth.find('john', 'invalid11').should_not == @user
     end
 
     it "should not find user with invalid login and password" do
-      gl_auth.find('jon', 'invalid').should_not == @user
+      gl_auth.find('jon', 'invalid11').should_not == @user
     end
   end
 end
diff --git a/spec/models/assembla_service_spec.rb b/spec/models/assembla_service_spec.rb
new file mode 100644 (file)
index 0000000..0b961c8
--- /dev/null
@@ -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)
+#  subdomain   :string(255)
+#  room        :string(255)
+#
+
+require 'spec_helper'
+
+describe AssemblaService 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
+      @assembla_service = AssemblaService.new
+      @assembla_service.stub(
+        project_id: project.id,
+        project: project,
+        service_hook: true,
+        token: 'verySecret'
+      )
+      @sample_data = GitPushService.new.sample_data(project, user)
+      @api_url = 'https://atlas.assembla.com/spaces/ouposp/github_tool?secret_key=verySecret'
+      WebMock.stub_request(:post, @api_url)
+    end
+
+    it "should call FlowDock API" do
+      @assembla_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
index 8b9e0b3..59f75ae 100644 (file)
@@ -90,8 +90,8 @@ describe User do
     end
 
     it "should not generate password by default" do
-      user = create(:user, password: 'abcdefg')
-      user.password.should == 'abcdefg'
+      user = create(:user, password: 'abcdefghe')
+      user.password.should == 'abcdefghe'
     end
 
     it "should generate password when forcing random password" do
index 345f2ba..2d1f8df 100644 (file)
@@ -12,7 +12,7 @@ describe API::API do
   describe "POST /projects/:id/repository/files" do
     let(:valid_params) {
       {
-        file_name: 'newfile.rb',
+        file_path: 'newfile.rb',
         branch_name: 'master',
         content: 'puts 8',
         commit_message: 'Added newfile'
@@ -26,7 +26,7 @@ describe API::API do
 
       post api("/projects/#{project.id}/repository/files", user), valid_params
       response.status.should == 201
-      json_response['file_name'].should == 'newfile.rb'
+      json_response['file_path'].should == 'newfile.rb'
     end
 
     it "should return a 400 bad request if no params given" do
@@ -78,4 +78,38 @@ describe API::API do
       response.status.should == 400
     end
   end
+
+  describe "DELETE /projects/:id/repository/files" do
+    let(:valid_params) {
+      {
+        file_path: 'spec/spec_helper.rb',
+        branch_name: 'master',
+        commit_message: 'Changed file'
+      }
+    }
+
+    it "should delete existing file in project repo" do
+      Gitlab::Satellite::DeleteFileAction.any_instance.stub(
+        commit!: true,
+      )
+
+      delete api("/projects/#{project.id}/repository/files", user), valid_params
+      response.status.should == 200
+      json_response['file_path'].should == 'spec/spec_helper.rb'
+    end
+
+    it "should return a 400 bad request if no params given" do
+      delete api("/projects/#{project.id}/repository/files", user)
+      response.status.should == 400
+    end
+
+    it "should return a 400 if satellite fails to create file" do
+      Gitlab::Satellite::DeleteFileAction.any_instance.stub(
+        commit!: false,
+      )
+
+      delete api("/projects/#{project.id}/repository/files", user), valid_params
+      response.status.should == 400
+    end
+  end
 end
index 2ae186b..e4cef6c 100644 (file)
@@ -36,6 +36,32 @@ describe API::API do
     end
   end
 
+  describe "GET /projects/all" do
+    context "when unauthenticated" do
+      it "should return authentication error" do
+        get api("/projects/all")
+        response.status.should == 401
+      end
+    end
+
+    context "when authenticated as regular user" do
+      it "should return authentication error" do
+        get api("/projects/all", user)
+        response.status.should == 403
+      end
+    end
+
+    context "when authenticated as admin" do
+      it "should return an array of all projects" do
+        get api("/projects/all", admin)
+        response.status.should == 200
+        json_response.should be_an Array
+        json_response.first['name'].should == project.name
+        json_response.first['owner']['email'].should == user.email
+      end
+    end
+  end
+
   describe "POST /projects" do
     context "maximum number of projects reached" do
       before do
index 0fd90c5..668007d 100644 (file)
@@ -8,7 +8,7 @@ describe API::API do
   describe "POST /session" do
     context "when valid password" do
       it "should return private token" do
-        post api("/session"), email: user.email, password: '123456'
+        post api("/session"), email: user.email, password: '12345678'
         response.status.should == 201
 
         json_response['email'].should == user.email
index 025534a..cc0ec2f 100644 (file)
@@ -16,7 +16,7 @@ module LoginHelpers
   def login_with(user)
     visit new_user_session_path
     fill_in "user_login", with: user.email
-    fill_in "user_password", with: "123456"
+    fill_in "user_password", with: "12345678"
     click_button "Sign in"
     Thread.current[:current_user] = user
   end
index 87dffe1..e2bc2a5 100644 (file)
@@ -69,7 +69,8 @@ module TestEnv
       remove_repository: true,
       update_repository_head: true,
       add_key: true,
-      remove_key: true
+      remove_key: true,
+      version: '6.3.0'
     )
 
     Gitlab::Satellite::Satellite.any_instance.stub(