summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Ziebell <sebastian.ziebell@asquera.de>2013-03-07 14:51:56 +0100
committerSebastian Ziebell <sebastian.ziebell@asquera.de>2013-03-07 14:51:56 +0100
commit3374027e3a4e4eb040e59294a9ced9d7886a71e2 (patch)
tree4587984396a32047a6337e7810a39633ba683545
parent39114d259c6e4bd5bb60b18f561d06cc24e8c852 (diff)
parent9c2a6e201388e7e30987a8679ddfa65b9422a38c (diff)
downloadgitlab-ce-3374027e3a4e4eb040e59294a9ced9d7886a71e2.tar.gz
Merge branch 'master' into fixes/api, code clean up and tests fixed
Conflicts: doc/api/projects.md spec/requests/api/projects_spec.rb
-rw-r--r--Capfile.example4
-rw-r--r--Gemfile5
-rw-r--r--Gemfile.lock19
-rw-r--r--README.md31
-rw-r--r--app/assets/javascripts/tree.js.coffee14
-rw-r--r--app/assets/stylesheets/gitlab_bootstrap/blocks.scss7
-rw-r--r--app/assets/stylesheets/gitlab_bootstrap/common.scss1
-rw-r--r--app/assets/stylesheets/sections/projects.scss13
-rw-r--r--app/models/merge_request.rb2
-rw-r--r--app/models/repository.rb19
-rw-r--r--app/services/git_push_service.rb1
-rw-r--r--app/views/devise/sessions/_new_ldap.html.haml2
-rw-r--r--app/views/events/_event.html.haml23
-rw-r--r--app/views/help/api.html.haml11
-rw-r--r--app/views/help/index.html.haml2
-rw-r--r--app/views/layouts/public.html.haml2
-rw-r--r--app/views/projects/_form.html.haml8
-rw-r--r--app/views/projects/show.html.haml29
-rw-r--r--app/views/public/projects/index.html.haml28
-rw-r--r--app/views/tree/_tree.html.haml5
-rw-r--r--config/deploy.rb.example72
-rw-r--r--config/environments/production.rb2
-rw-r--r--config/initializers/4_sidekiq.rb6
-rw-r--r--config/resque.yml.example6
-rw-r--r--config/routes.rb6
-rw-r--r--doc/api/README.md13
-rw-r--r--doc/api/groups.md11
-rw-r--r--doc/api/projects.md124
-rw-r--r--doc/api/snippets.md8
-rw-r--r--doc/api/system_hooks.md47
-rw-r--r--doc/api/users.md17
-rw-r--r--doc/install/installation.md2
-rw-r--r--features/steps/project/project_network_graph.rb2
-rw-r--r--lib/api.rb1
-rw-r--r--lib/api/groups.rb18
-rw-r--r--lib/api/merge_requests.rb2
-rw-r--r--lib/api/projects.rb75
-rw-r--r--lib/api/system_hooks.rb60
-rw-r--r--lib/api/users.rb20
-rw-r--r--lib/extracts_path.rb6
-rw-r--r--lib/tasks/gitlab/setup.rake10
-rw-r--r--spec/controllers/commits_controller_spec.rb2
-rw-r--r--spec/requests/api/groups_spec.rb23
-rw-r--r--spec/requests/api/notes_spec.rb14
-rw-r--r--spec/requests/api/projects_spec.rb98
-rw-r--r--spec/requests/api/system_hooks_spec.rb69
-rw-r--r--spec/requests/api/users_spec.rb16
-rw-r--r--spec/routing/project_routing_spec.rb20
-rw-r--r--spec/support/stubbed_repository.rb5
49 files changed, 819 insertions, 162 deletions
diff --git a/Capfile.example b/Capfile.example
new file mode 100644
index 00000000000..8863835da4a
--- /dev/null
+++ b/Capfile.example
@@ -0,0 +1,4 @@
+load 'deploy'
+load 'deploy/assets'
+require 'bundler/capistrano'
+load 'config/deploy'
diff --git a/Gemfile b/Gemfile
index cf1617c316a..324e1ce2c1b 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,4 +1,4 @@
-source "http://rubygems.org"
+source "https://rubygems.org"
def darwin_only(require_as)
RUBY_PLATFORM.include?('darwin') && require_as
@@ -103,6 +103,9 @@ gem 'settingslogic'
gem "foreman"
gem "git"
+# Cache
+gem "redis-rails"
+
group :assets do
gem "sass-rails", "~> 3.2.5"
gem "coffee-rails", "~> 3.2.2"
diff --git a/Gemfile.lock b/Gemfile.lock
index 89882492b36..36447188359 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -13,7 +13,7 @@ GIT
raphael-rails (2.1.0)
GEM
- remote: http://rubygems.org/
+ remote: https://rubygems.org/
specs:
actionmailer (3.2.12)
actionpack (= 3.2.12)
@@ -329,8 +329,24 @@ GEM
json (~> 1.4)
redcarpet (2.2.2)
redis (3.0.2)
+ redis-actionpack (3.2.3)
+ actionpack (~> 3.2.3)
+ redis-rack (~> 1.4.0)
+ redis-store (~> 1.1.0)
+ redis-activesupport (3.2.3)
+ activesupport (~> 3.2.3)
+ redis-store (~> 1.1.0)
redis-namespace (1.2.1)
redis (~> 3.0.0)
+ redis-rack (1.4.2)
+ rack (~> 1.4.1)
+ redis-store (~> 1.1.0)
+ redis-rails (3.2.3)
+ redis-actionpack (~> 3.2.3)
+ redis-activesupport (~> 3.2.3)
+ redis-store (~> 1.1.0)
+ redis-store (1.1.3)
+ redis (>= 2.2.0)
request_store (1.0.5)
rspec (2.12.0)
rspec-core (~> 2.12.0)
@@ -504,6 +520,7 @@ DEPENDENCIES
rb-fsevent
rb-inotify
redcarpet (~> 2.2.2)
+ redis-rails
rspec-rails (= 2.12.2)
sass-rails (~> 3.2.5)
sdoc
diff --git a/README.md b/README.md
index 02b4722f4be..00a8a88911f 100644
--- a/README.md
+++ b/README.md
@@ -5,14 +5,14 @@
### GitLab allows you to
* keep your code secure on your own server
* manage repositories, users and access permissions
- * communicate though issues, line-comments and wiki's
- * perform code reviews with merge requests
+ * communicate through issues, line-comments and wiki pages
+ * perform code review with merge requests
### GitLab is
* powered by Ruby on Rails
* completely free and open source (MIT license)
-* used by 10.000 organization to keep their code secure
+* used by 10.000 organizations to keep their code secure
### Code status
@@ -34,28 +34,35 @@
### Requirements
-* Ubuntu/Debian*
+* Ubuntu/Debian**
* ruby 1.9.3+
* MySQL
* git
* gitlab-shell
* redis
-* More details are in the [requirements doc](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/requirements.md)
+** More details are in the [requirements doc](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/requirements.md)
### Installation
-You can either follow the "ordinary" Installation guide to install it on a machine or use the Vagrant virtual machine. The Installation guide is recommended to set up a production server. The Vargrant virtual machine is recommended for development since it makes it much easier to set up all the dependencies for integration testing.
+#### For production
-* [Installation guide for latest stable release](https://github.com/gitlabhq/gitlabhq/blob/4-2-stable/doc/install/installation.md)
+Follow the installation guide for production server.
-* [Installation guide for the current master branch](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md)
+* [Installation guide for latest stable release (4.2)](https://github.com/gitlabhq/gitlabhq/blob/4-2-stable/doc/install/installation.md) - **Recommended**
+
+* [Installation guide for the current master branch (5.0)](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md)
+
+
+#### For development
+
+If you want to contribute, please first read our [Contributing Guidelines](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) and then we suggest you to use the Vagrant virtual machine project to get an environment working sandboxed and with all dependencies.
* [Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm)
### Starting
-1. The Installation guide contains instructions to download an init script and run that on boot. With the init script you can also start GitLab with:
+1. The Installation guide contains instructions to download an init script and run that on boot. With the init script you can also start GitLab
sudo service gitlab start
@@ -63,18 +70,18 @@ You can either follow the "ordinary" Installation guide to install it on a machi
sudo /etc/init.d/gitlab restart
-2. Start it with [Foreman](https://github.com/ddollar/foreman) in development model
+2. Start it with [Foreman](https://github.com/ddollar/foreman) in development mode
bundle exec foreman start -p 3000
-3. Start it manually in development mode
+ or start it manually
bundle exec rails s
bundle exec rake sidekiq:start
### Running the tests
-* Seed the database with
+* Seed the database
bundle exec rake db:setup RAILS_ENV=test
bundle exec rake db:seed_fu RAILS_ENV=test
diff --git a/app/assets/javascripts/tree.js.coffee b/app/assets/javascripts/tree.js.coffee
index 5003f9b00c7..2603b9a96c6 100644
--- a/app/assets/javascripts/tree.js.coffee
+++ b/app/assets/javascripts/tree.js.coffee
@@ -11,12 +11,7 @@ $ ->
# Make the entire tree-item row clickable, but not if clicking another link (like a commit message)
$("#tree-slider .tree-item").live 'click', (e) ->
$('.tree-item-file-name a', this).trigger('click') if (e.target.nodeName != "A")
-
- # Show/Hide the loading spinner
- $('#tree-slider .tree-item-file-name a, .breadcrumb a, .project-refs-form').live
- "ajax:beforeSend": -> $('.tree_progress').addClass("loading")
- "ajax:complete": -> $('.tree_progress').removeClass("loading")
-
+
# Maintain forward/back history while browsing the file tree
((window) ->
History = window.History
@@ -33,7 +28,12 @@ $ ->
History.Adapter.bind window, 'statechange', ->
state = History.getState()
- window.ajaxGet(state.url)
+ $.ajax({
+ url: state.url,
+ dataType: 'script',
+ beforeSend: -> $('.tree_progress').addClass("loading"),
+ complete: -> $('.tree_progress').removeClass("loading")
+ })
)(window)
# See if there are lines selected
diff --git a/app/assets/stylesheets/gitlab_bootstrap/blocks.scss b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
index 4d1b6446362..ce939bc26ca 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
@@ -34,13 +34,6 @@
padding: 15px;
word-wrap: break-word;
- pre {
- background: none !important;
- margin: 0;
- border: none;
- padding: 0;
- }
-
.clearfix {
margin: 0;
}
diff --git a/app/assets/stylesheets/gitlab_bootstrap/common.scss b/app/assets/stylesheets/gitlab_bootstrap/common.scss
index 9e015eb2b6e..00d2e88a360 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/common.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/common.scss
@@ -2,6 +2,7 @@
.cgray { color:gray }
.cred { color:#D12F19 }
.cgreen { color:#4a2 }
+.cblue { color:#29A }
.cblack { color:#111 }
.cdark { color:#444 }
.cwhite { color:#fff!important }
diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss
index ada0780eece..3abda7ee69e 100644
--- a/app/assets/stylesheets/sections/projects.scss
+++ b/app/assets/stylesheets/sections/projects.scss
@@ -120,3 +120,16 @@ ul.nav.nav-projects-tabs {
.team_member_row form {
margin: 0px;
}
+
+.public-projects {
+ li {
+ margin-top: 8px;
+ margin-bottom: 5px;
+ border-bottom: 1px solid #eee;
+
+ .description {
+ margin-left: 22px;
+ color: #aaa;
+ }
+ }
+}
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index c26d40c5703..354a95e9a93 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -91,7 +91,7 @@ class MergeRequest < ActiveRecord::Base
def validate_branches
if target_branch == source_branch
- errors.add :base, "You can not use same branch for source and target branches"
+ errors.add :branch_conflict, "You can not use same branch for source and target branches"
end
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 3feb3180347..934c1a6e086 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -1,4 +1,6 @@
class Repository
+ include Gitlab::Popen
+
# Repository directory name with namespace direcotry
# Examples:
# gitlab/gitolite
@@ -147,4 +149,21 @@ class Repository
file_path
end
+
+ # Return repo size in megabytes
+ # Cached in redis
+ def size
+ Rails.cache.fetch(cache_key(:size)) do
+ size = popen('du -s', path_to_repo).first.strip.to_i
+ (size.to_f / 1024).round(2)
+ end
+ end
+
+ def expire_cache
+ Rails.cache.delete(cache_key(:size))
+ end
+
+ def cache_key(type)
+ "#{type}:#{path_with_namespace}"
+ end
end
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index 208ccf699d2..d0b3dd557a1 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -23,6 +23,7 @@ class GitPushService
project.ensure_satellite_exists
project.discover_default_branch
+ project.repository.expire_cache
if push_to_branch?(ref, oldrev)
project.update_merge_requests(oldrev, newrev, ref, @user)
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index 7968b0e9c9f..eb8c5194607 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -1,6 +1,6 @@
= form_tag(user_omniauth_callback_path(:ldap), :class => "login-box", :id => 'new_ldap_user' ) do
= image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo"
- = text_field_tag :username, nil, {:class => "text top", :placeholder => "LDAP Login"}
+ = text_field_tag :username, nil, {:class => "text top", :placeholder => "LDAP Login", :autofocus => "autofocus"}
= password_field_tag :password, nil, {:class => "text bottom", :placeholder => "Password"}
%br/
= submit_tag "LDAP Sign in", :class => "btn-primary btn"
diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml
index 719f6c3787f..febd72f699b 100644
--- a/app/views/events/_event.html.haml
+++ b/app/views/events/_event.html.haml
@@ -1,15 +1,16 @@
- if event.proper?
- %div.event-item
- %span.cgray.pull-right
- #{time_ago_in_words(event.created_at)} ago.
+ = cache event do
+ %div.event-item
+ %span.cgray.pull-right
+ #{time_ago_in_words(event.created_at)} ago.
- = image_tag gravatar_icon(event.author_email), class: "avatar s24"
+ = image_tag gravatar_icon(event.author_email), class: "avatar s24"
- - if event.push?
- = render "events/event/push", event: event
- .clearfix
- - elsif event.note?
- = render "events/event/note", event: event
- - else
- = render "events/event/common", event: event
+ - if event.push?
+ = render "events/event/push", event: event
+ .clearfix
+ - elsif event.note?
+ = render "events/event/note", event: event
+ - else
+ = render "events/event/common", event: event
diff --git a/app/views/help/api.html.haml b/app/views/help/api.html.haml
index d771f1e9f38..0c502ada8fa 100644
--- a/app/views/help/api.html.haml
+++ b/app/views/help/api.html.haml
@@ -21,6 +21,8 @@
= link_to "Milestones", "#milestones", 'data-toggle' => 'tab'
%li
= link_to "Notes", "#notes", 'data-toggle' => 'tab'
+ %li
+ = link_to "System Hooks", "#system_hooks", 'data-toggle' => 'tab'
.tab-content
.tab-pane.active#README
@@ -103,3 +105,12 @@
.file_content.wiki
= preserve do
= markdown File.read(Rails.root.join("doc", "api", "notes.md"))
+
+ .tab-pane#system_hooks
+ .file_holder
+ .file_title
+ %i.icon-file
+ System Hooks
+ .file_content.wiki
+ = preserve do
+ = markdown File.read(Rails.root.join("doc", "api", "system_hooks.md"))
diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml
index 879a19fdfb4..78b2951122b 100644
--- a/app/views/help/index.html.haml
+++ b/app/views/help/index.html.haml
@@ -22,7 +22,7 @@
= mail_to Gitlab.config.gitlab.support_email, "support contact"
%li
Use the
- = link_to "search bar", '#', onclick: "$("#search").focus();"
+ = link_to "search bar", '#', onclick: "$('#search').focus();"
on the top of this page
%li
Ask in our
diff --git a/app/views/layouts/public.html.haml b/app/views/layouts/public.html.haml
index fa368e9be2e..435250b6825 100644
--- a/app/views/layouts/public.html.haml
+++ b/app/views/layouts/public.html.haml
@@ -10,7 +10,7 @@
= link_to root_path, class: "home" do
%h1 GITLAB
%span.separator
- %h1.project_name Public Projects
+ %h1.project_name Public Projects
.container
.content
.prepend-top-20
diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml
index b78c70be18a..a7930680881 100644
--- a/app/views/projects/_form.html.haml
+++ b/app/views/projects/_form.html.haml
@@ -9,11 +9,19 @@
Project name is
.input
= f.text_field :name, placeholder: "Example Project", class: "xxlarge"
+
+
- unless @repository.heads.empty?
.clearfix
= f.label :default_branch, "Default Branch"
.input= f.select(:default_branch, @repository.heads.map(&:name), {}, style: "width:210px;")
+ .clearfix
+ = f.label :description do
+ Project description
+ %span.light (optional)
+ .input
+ = f.text_area :description, placeholder: "awesome project", class: "xxlarge", rows: 3, maxlength: 250
%fieldset.features
%legend Features:
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 2c4f55eb646..861930cab35 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -1,8 +1,33 @@
= render "project_head"
= render 'clone_panel'
= render "events/event_last_push", event: @last_push
-.content_list= render @events
-.loading.hide
+.row
+ .span9
+ .content_list= render @events
+ .loading.hide
+ .span3
+ .ui-box.white
+ .padded
+ %h3.page_title
+ = @project.name
+ - if @project.description.present?
+ %p.light= @project.description
+
+ %hr
+ %p
+ Access level:
+ - if @project.public
+ %span.cblue
+ %i.icon-share
+ Public
+ - else
+ %span.cgreen
+ %i.icon-lock
+ Private
+
+ %p Repo Size: #{@project.repository.size} MB
+ %p Created at: #{@project.created_at.stamp('Aug 22, 2013')}
+ %p Owner: #{link_to @project.owner_name, @project.owner}
:javascript
$(function(){ Pager.init(20); });
diff --git a/app/views/public/projects/index.html.haml b/app/views/public/projects/index.html.haml
index 52e01c3d56e..b50484f6354 100644
--- a/app/views/public/projects/index.html.haml
+++ b/app/views/public/projects/index.html.haml
@@ -1,18 +1,20 @@
%h3.page_title
- Projects
+ Projects (#{@projects.total_count})
%small with read-only access
%hr
-%ul.unstyled
- - @projects.each do |project|
- %li.clearfix
- %h5
- %i.icon-share
- = project.name_with_namespace
- .pull-right
- %pre.dark.tiny git clone #{project.http_url_to_repo}
+.public-projects
+ %ul.unstyled
+ - @projects.each do |project|
+ %li.clearfix
+ %h5
+ %i.icon-share
+ = project.name_with_namespace
+ .pull-right
+ %pre.dark.tiny git clone #{project.http_url_to_repo}
+ %p.description
+ = project.description
+ - unless @projects.present?
+ %h3.nothing_here_message No public projects
- - unless @projects.present?
- %h3.nothing_here_message No public projects
-
-= paginate @projects, theme: "admin"
+ = paginate @projects, theme: "admin"
diff --git a/app/views/tree/_tree.html.haml b/app/views/tree/_tree.html.haml
index 29a2ed02d31..dc3a84404a3 100644
--- a/app/views/tree/_tree.html.haml
+++ b/app/views/tree/_tree.html.haml
@@ -11,9 +11,6 @@
- else
= link_to title, '#'
-.clear
-%div.tree_progress
-
%div#tree-content-holder.tree-content-holder
- if tree.is_blob?
= render "tree/blob", blob: tree
@@ -40,6 +37,8 @@
- if tree.readme
= render "tree/readme", readme: tree.readme
+%div.tree_progress
+
- unless tree.is_blob?
:javascript
// Load last commit log for each file in tree
diff --git a/config/deploy.rb.example b/config/deploy.rb.example
new file mode 100644
index 00000000000..ddce4671b58
--- /dev/null
+++ b/config/deploy.rb.example
@@ -0,0 +1,72 @@
+set :domain, 'set application domain here'
+set :db_adapter, 'mysql' # or postgres
+set :mount_point, '/'
+set :application, 'gitlabhq'
+set :user, 'git'
+set :rails_env, 'production'
+set :deploy_to, "/home/#{user}/apps/#{application}"
+set :bundle_without, %w[development test] + (%w[mysql postgres] - [db_adapter])
+set :asset_env, "RAILS_GROUPS=assets RAILS_RELATIVE_URL_ROOT=#{mount_point.sub /\/+\Z/, ''}"
+
+set :use_sudo, false
+default_run_options[:pty] = true
+
+# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`
+set :scm, :git
+set :repository, "git@#{domain}:#{application}.git"
+set :deploy_via, :remote_cache
+
+# Alternatively, you can deploy via copy, if you don't have gitlab in git
+#set :scm, :none
+#set :repository, '.'
+#set :deploy_via, :copy
+
+server domain, :app, :web, :db, primary: true
+
+namespace :foreman do
+ desc 'Export the Procfile to Ubuntu upstart scripts'
+ task :export, roles: :app do
+ foreman_export = "foreman export upstart /etc/init -f Procfile -a #{application} -u #{user} -l #{shared_path}/log/foreman"
+ run "cd #{release_path} && #{sudo} #{fetch :bundle_cmd, 'bundle'} exec #{foreman_export}"
+ end
+
+ desc 'Start the application services'
+ task :start, roles: :app do
+ run "#{sudo} service #{application} start"
+ end
+
+ desc 'Stop the application services'
+ task :stop, roles: :app do
+ run "#{sudo} service #{application} stop"
+ end
+
+ desc 'Restart the application services'
+ task :restart, roles: :app do
+ run "#{sudo} service #{application} restart"
+ end
+end
+
+namespace :deploy do
+ desc 'Start the application services'
+ task :start, roles: :app do
+ foreman.start
+ end
+
+ desc 'Stop the application services'
+ task :stop, roles: :app do
+ foreman.stop
+ end
+
+ desc 'Restart the application services'
+ task :restart, roles: :app do
+ foreman.restart
+ end
+end
+
+after 'deploy:cold' do
+ run "cd #{release_path} && #{rake} gitlab:setup force=yes RAILS_ENV=#{rails_env}"
+ deploy.restart
+end
+
+after 'deploy:update', 'foreman:export' # Export foreman scripts
+#after 'deploy:update', 'foreman:restart' # Restart application scripts
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 52fb8877cf3..6ae0324fa8c 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -40,7 +40,7 @@ Gitlab::Application.configure do
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# Use a different cache store in production
- config.cache_store = :memory_store
+ config.cache_store = :redis_store
# Enable serving of images, stylesheets, and JavaScripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
diff --git a/config/initializers/4_sidekiq.rb b/config/initializers/4_sidekiq.rb
index 6abe6e74fa0..c90d376273d 100644
--- a/config/initializers/4_sidekiq.rb
+++ b/config/initializers/4_sidekiq.rb
@@ -4,19 +4,19 @@ config_file = Rails.root.join('config', 'resque.yml')
resque_url = if File.exists?(config_file)
YAML.load_file(config_file)[Rails.env]
else
- "localhost:6379"
+ "redis://localhost:6379"
end
Sidekiq.configure_server do |config|
config.redis = {
- url: "redis://#{resque_url}",
+ url: resque_url,
namespace: 'resque:gitlab'
}
end
Sidekiq.configure_client do |config|
config.redis = {
- url: "redis://#{resque_url}",
+ url: resque_url,
namespace: 'resque:gitlab'
}
end
diff --git a/config/resque.yml.example b/config/resque.yml.example
index cd3d487408a..3c7ad0e5778 100644
--- a/config/resque.yml.example
+++ b/config/resque.yml.example
@@ -1,3 +1,3 @@
-development: localhost:6379
-test: localhost:6379
-production: redis.example.com:6379
+development: redis://localhost:6379
+test: redis://localhost:6379
+production: redis://redis.example.com:6379
diff --git a/config/routes.rb b/config/routes.rb
index c8e7c8ee4f8..b06fda8f85d 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -166,7 +166,7 @@ Gitlab::Application.routes.draw do
#
# Project Area
#
- resources :projects, constraints: { id: /[a-zA-Z.0-9_\-\/]+/ }, except: [:new, :create, :index], path: "/" do
+ resources :projects, constraints: { id: /(?:[a-zA-Z.0-9_\-]+\/)?[a-zA-Z.0-9_\-]+/ }, except: [:new, :create, :index], path: "/" do
member do
get "wall"
get "files"
@@ -175,10 +175,10 @@ Gitlab::Application.routes.draw do
resources :blob, only: [:show], constraints: {id: /.+/}
resources :tree, only: [:show, :edit, :update], constraints: {id: /.+/}
resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/}
- resources :commits, only: [:show], constraints: {id: /.+/}
+ resources :commits, only: [:show], constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/}
resources :compare, only: [:index, :create]
resources :blame, only: [:show], constraints: {id: /.+/}
- resources :graph, only: [:show], constraints: {id: /.+/}
+ resources :graph, only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/}
match "/compare/:from...:to" => "compare#show", as: "compare",
:via => [:get, :post], constraints: {from: /.+/, to: /.+/}
diff --git a/doc/api/README.md b/doc/api/README.md
index 2699434d00b..f6c4e41b6cd 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -31,13 +31,10 @@ The API uses JSON to serialize data. You don't need to specify `.json` at the en
## Status codes
-API requests return different status codes according to
-
-The API is designed to provide status codes according to the context and how the request
-is handled. For example if a `GET` request is successful a status code `200 Ok`
-is returned. The API is designed to be RESTful.
-
-The following list gives an overview of how the API functions are designed.
+The API is designed to return different status codes according to context and action. In this way
+if a request results in an error the caller is able to get insight into what went wrong, e.g.
+status code `400 Bad Request` is returned if a required attribute is missing from the request.
+The following list gives an overview of how the API functions generally behave.
API request types:
@@ -58,7 +55,7 @@ Return values:
* `403 Forbidden` - The request is not allowed, e.g. the user is not allowed to delete a project
* `404 Not Found` - A resource could not be accessed, e.g. an ID for a resource could not be found
* `405 Method Not Allowed` - The request is not supported
-* `409 Conflict` - A conflicting resource already exists, a project with same name already exists
+* `409 Conflict` - A conflicting resource already exists, e.g. creating a project with a name that already exists
* `500 Server Error` - While handling the request something went wrong on the server side
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 25b9741f68a..e9702ea2cd1 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -44,3 +44,14 @@ Parameters:
+ `name` (required) - The name of the group
+ `path` (required) - The path of the group
+## Transfer project to group
+
+Transfer a project to the Group namespace. Available only for admin
+
+```
+POST /groups/:id/projects/:project_id
+```
+
+Parameters:
++ `id` (required) - The ID of a group
++ `project_id (required) - The ID of a project
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 326a62b0154..d6a9a8854ca 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -115,11 +115,9 @@ Parameters:
+ `merge_requests_enabled` (optional) - enabled by default
+ `wiki_enabled` (optional) - enabled by default
+**Project access levels**
-## Project access levels
-
-The project access levels are defined in the `user_project` class. Currently, 4
-levels are recoginized:
+The project access levels are defined in the `user_project.rb` class. Currently, these levels are recoginized:
```
GUEST = 10
@@ -129,7 +127,30 @@ levels are recoginized:
```
-## List project team members
+### Create project for user
+
+Creates a new project owned by user. Available only for admins.
+
+```
+POST /projects/user/:user_id
+```
+
+Parameters:
+
++ `user_id` (required) - user_id of owner
++ `name` (required) - new project name
++ `description` (optional) - short project description
++ `default_branch` (optional) - 'master' by default
++ `issues_enabled` (optional) - enabled by default
++ `wall_enabled` (optional) - enabled by default
++ `merge_requests_enabled` (optional) - enabled by default
++ `wiki_enabled` (optional) - enabled by default
+
+
+
+## Team members
+
+### List project team members
Get a list of project team members.
@@ -140,14 +161,12 @@ GET /projects/:id/members
Parameters:
+ `id` (required) - The ID or NAME of a project
-+ `query` - Query string
-
++ `query` (optional) - Query string to search for members
-## Team members
### Get project team member
-Get a project team member.
+Gets a project team member.
```
GET /projects/:id/members/:user_id
@@ -175,7 +194,7 @@ Parameters:
Adds a user to a project team. This is an idempotent method and can be called multiple times
with the same parameters. Adding team membership to a user that is already a member does not
-affect the membership.
+affect the existing membership.
```
POST /projects/:id/members
@@ -190,7 +209,7 @@ Parameters:
### Edit project team member
-Update project team member to specified access level.
+Updates project team member to a specified access level.
```
PUT /projects/:id/members/:user_id
@@ -398,81 +417,90 @@ Returns values:
+ `404 Not Found` if project with id or the branch with `ref_name` not found
-## Snippets
-### List snippets
+## Deploy Keys
+
+### List deploy keys
-Lists the snippets of a project.
+Get a list of a project's deploy keys.
```
-GET /projects/:id/snippets
+GET /projects/:id/keys
```
Parameters:
+ `id` (required) - The ID of the project
-
-### List single snippet
-
-Lists a single snippet of a project
-
-```
-GET /projects/:id/snippets/:snippet_id
+```json
+[
+ {
+ "id": 1,
+ "title" : "Public key"
+ "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+ 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+ soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+ },
+ {
+ "id": 3,
+ "title" : "Another Public key"
+ "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+ 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+ soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+ }
+]
```
-Parameters:
-
-+ `id` (required) - The ID of the project
-+ `snippet_id` (required) - The ID of the snippet
+### Single deploy key
-### Create snippet
-
-Creates a new project snippet.
+Get a single key.
```
-POST /projects/:id/snippets
+GET /projects/:id/keys/:key_id
```
Parameters:
+ `id` (required) - The ID of the project
-+ `title` (required) - The title of the new snippet
-+ `file_name` (required) - The file name of the snippet
-+ `code` (required) - The content of the snippet
-+ `lifetime` (optional) - The expiration date of a snippet
++ `key_id` (required) - The ID of the deploy key
+```json
+{
+ "id": 1,
+ "title" : "Public key"
+ "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+ 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+ soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+}
+```
-### Update snippet
-Updates an existing project snippet.
+### Add deploy key
+
+Creates a new deploy key for a project.
```
-PUT /projects/:id/snippets/:snippet_id
+POST /projects/:id/keys
```
Parameters:
+ `id` (required) - The ID of the project
-+ `snippet_id` (required) - The id of the project snippet
-+ `title` (optional) - The new title of the project snippet
-+ `file_name` (optional) - The new file name of the project snippet
-+ `lifetime` (optional) - The new expiration date of the snippet
-+ `code` (optional) - The content of the snippet
++ `title` (required) - New deploy key's title
++ `key` (required) - New deploy key
-## Delete snippet
+### Delete deploy key
-Deletes a project snippet. This is an idempotent function call and returns `200 Ok`
-even if the snippet with the id is not available.
+Delete a deploy key from a project
```
-DELETE /projects/:id/snippets/:snippet_id
+DELETE /projects/:id/keys/:key_id
```
-Paramaters:
+Parameters:
+ `id` (required) - The ID of the project
-+ `snippet_id` (required) - The ID of the snippet
++ `key_id` (required) - The ID of the deploy key
diff --git a/doc/api/snippets.md b/doc/api/snippets.md
index 4becc928b1f..04ea367d518 100644
--- a/doc/api/snippets.md
+++ b/doc/api/snippets.md
@@ -46,7 +46,7 @@ Parameters:
## Create new snippet
-Creates a new project snippet.
+Creates a new project snippet. The user must have permission to create new snippets.
```
POST /projects/:id/snippets
@@ -61,9 +61,9 @@ Parameters:
+ `code` (required) - The content of a snippet
-## Edit snippet
+## Update snippet
-Updates an existing project snippet.
+Updates an existing project snippet. The user must have permission to change an existing snippet.
```
PUT /projects/:id/snippets/:snippet_id
@@ -96,7 +96,7 @@ Parameters:
## Snippet content
-Get a raw project snippet.
+Returns the raw project snippet as plain text.
```
GET /projects/:id/snippets/:snippet_id/raw
diff --git a/doc/api/system_hooks.md b/doc/api/system_hooks.md
new file mode 100644
index 00000000000..f6e11ed238e
--- /dev/null
+++ b/doc/api/system_hooks.md
@@ -0,0 +1,47 @@
+All methods require admin authorization.
+
+## List system hooks
+
+Get list of system hooks
+
+```
+GET /hooks
+```
+
+Will return hooks with status `200 OK` on success, or `404 Not found` on fail.
+
+## Add new system hook hook
+
+```
+POST /hooks
+```
+
+Parameters:
+
++ `url` (required) - The hook URL
+
+Will return status `201 Created` on success, or `404 Not found` on fail.
+
+## Test system hook
+
+```
+GET /hooks/:id
+```
+
+Parameters:
+
++ `id` (required) - The ID of hook
+
+Will return hook with status `200 OK` on success, or `404 Not found` on fail.
+
+## Delete system hook
+
+```
+DELETE /hooks/:id
+```
+
+Parameters:
+
++ `id` (required) - The ID of hook
+
+Will return status `200 OK` on success, or `404 Not found` on fail. \ No newline at end of file
diff --git a/doc/api/users.md b/doc/api/users.md
index 6d5c9d78412..dc31c10eb9d 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -235,6 +235,23 @@ Parameters:
+ `key` (required) - new SSH key
+## Add SSH key for user
+
+Create new key owned by specified user. Available only for admin
+
+```
+POST /users/:id/keys
+```
+
+Parameters:
+
++ `id` (required) - id of specified user
++ `title` (required) - new SSH Key's title
++ `key` (required) - new SSH key
+
+Will return created key with status `201 Created` on success, or `404 Not
+found` on fail.
+
## Delete SSH key
Deletes key owned by currently authenticated user. This is an idempotent function and calling it on a key that is already
diff --git a/doc/install/installation.md b/doc/install/installation.md
index d0f586af6b4..51a8dcfb876 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -288,7 +288,7 @@ a different host, you can configure its connection string via the
`config/resque.yml` file.
# example
- production: redis.example.tld:6379
+ production: redis://redis.example.tld:6379
## Custom SSH Connection
diff --git a/features/steps/project/project_network_graph.rb b/features/steps/project/project_network_graph.rb
index 2ca629883a9..7e9a7c295d0 100644
--- a/features/steps/project/project_network_graph.rb
+++ b/features/steps/project/project_network_graph.rb
@@ -27,6 +27,7 @@ class ProjectNetworkGraph < Spinach::FeatureSteps
And 'I switch ref to "stable"' do
page.select 'stable', :from => 'ref'
+ sleep 2
end
And 'page should select "stable" in select box' do
@@ -44,6 +45,7 @@ class ProjectNetworkGraph < Spinach::FeatureSteps
fill_in 'q', :with => '98d6492'
find('button').click
end
+ sleep 2
end
And 'page should have "v2.1.0" on graph' do
diff --git a/lib/api.rb b/lib/api.rb
index 3264f6a8fa6..d241f9b7479 100644
--- a/lib/api.rb
+++ b/lib/api.rb
@@ -33,5 +33,6 @@ module Gitlab
mount MergeRequests
mount Notes
mount Internal
+ mount SystemHooks
end
end
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 5aaa5eb4f54..beb615195a8 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -56,6 +56,24 @@ module Gitlab
not_found!
end
end
+
+ # Transfer a project to the Group namespace
+ #
+ # Parameters:
+ # id - group id
+ # project_id - project id
+ # Example Request:
+ # POST /groups/:id/projects/:project_id
+ post ":id/projects/:project_id" do
+ authenticated_as_admin!
+ @group = Group.find(params[:id])
+ project = Project.find(params[:project_id])
+ if project.transfer(@group)
+ present @group
+ else
+ not_found!
+ end
+ end
end
end
end
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 5adf57b36c5..234a005a998 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -8,6 +8,8 @@ module Gitlab
def handle_merge_request_errors!(errors)
if errors[:project_access].any?
error!(errors[:project_access], 422)
+ elsif errors[:branch_conflict].any?
+ error!(errors[:branch_conflict], 422)
end
not_found!
end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index b8efef318d3..b1d6357fbbb 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -64,6 +64,38 @@ module Gitlab
end
end
+ # Create new project for a specified user. Only available to admin users.
+ #
+ # Parameters:
+ # user_id (required) - The ID of a user
+ # name (required) - name for new project
+ # description (optional) - short project description
+ # default_branch (optional) - 'master' by default
+ # issues_enabled (optional) - enabled by default
+ # wall_enabled (optional) - enabled by default
+ # merge_requests_enabled (optional) - enabled by default
+ # wiki_enabled (optional) - enabled by default
+ # Example Request
+ # POST /projects/user/:user_id
+ post "user/:user_id" do
+ authenticated_as_admin!
+ user = User.find(params[:user_id])
+ attrs = attributes_for_keys [:name,
+ :description,
+ :default_branch,
+ :issues_enabled,
+ :wall_enabled,
+ :merge_requests_enabled,
+ :wiki_enabled]
+ @project = ::Projects::CreateContext.new(user, attrs).execute
+ if @project.saved?
+ present @project, with: Entities::Project
+ else
+ not_found!
+ end
+ end
+
+
# Get a project team members
#
# Parameters:
@@ -471,6 +503,49 @@ module Gitlab
present tree.data
end
+ # Get a specific project's keys
+ #
+ # Example Request:
+ # GET /projects/:id/keys
+ get ":id/keys" do
+ present user_project.deploy_keys, with: Entities::SSHKey
+ end
+
+ # Get single key owned by currently authenticated user
+ #
+ # Example Request:
+ # GET /projects/:id/keys/:id
+ get ":id/keys/:key_id" do
+ key = user_project.deploy_keys.find params[:key_id]
+ present key, with: Entities::SSHKey
+ end
+
+ # Add new ssh key to currently authenticated user
+ #
+ # Parameters:
+ # key (required) - New SSH Key
+ # title (required) - New SSH Key's title
+ # Example Request:
+ # POST /projects/:id/keys
+ post ":id/keys" do
+ attrs = attributes_for_keys [:title, :key]
+ key = user_project.deploy_keys.new attrs
+ if key.save
+ present key, with: Entities::SSHKey
+ else
+ not_found!
+ end
+ end
+
+ # Delete existed ssh key of currently authenticated user
+ #
+ # Example Request:
+ # DELETE /projects/:id/keys/:id
+ delete ":id/keys/:key_id" do
+ key = user_project.deploy_keys.find params[:key_id]
+ key.delete
+ end
+
end
end
end
diff --git a/lib/api/system_hooks.rb b/lib/api/system_hooks.rb
new file mode 100644
index 00000000000..665a1cdd0d2
--- /dev/null
+++ b/lib/api/system_hooks.rb
@@ -0,0 +1,60 @@
+module Gitlab
+ # Hooks API
+ class SystemHooks < Grape::API
+ before { authenticated_as_admin! }
+
+ resource :hooks do
+ # Get the list of system hooks
+ #
+ # Example Request:
+ # GET /hooks
+ get do
+ @hooks = SystemHook.all
+ present @hooks, with: Entities::Hook
+ end
+
+ # Create new system hook
+ #
+ # Parameters:
+ # url (required) - url for system hook
+ # Example Request
+ # POST /hooks
+ post do
+ attrs = attributes_for_keys [:url]
+ @hook = SystemHook.new attrs
+ if @hook.save
+ present @hook, with: Entities::Hook
+ else
+ not_found!
+ end
+ end
+
+ # Test a hook
+ #
+ # Example Request
+ # GET /hooks/:id
+ get ":id" do
+ @hook = SystemHook.find(params[:id])
+ data = {
+ event_name: "project_create",
+ name: "Ruby",
+ path: "ruby",
+ project_id: 1,
+ owner_name: "Someone",
+ owner_email: "example@gitlabhq.com"
+ }
+ @hook.execute(data)
+ data
+ end
+
+ # Delete a hook
+ #
+ # Example Request:
+ # DELETE /hooks/:id
+ delete ":id" do
+ @hook = SystemHook.find(params[:id])
+ @hook.destroy
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 5e0680de71a..6cc3a7e52c9 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -81,6 +81,26 @@ module Gitlab
end
end
+ # Add ssh key to a specified user. Only available to admin users.
+ #
+ # Parameters:
+ # id (required) - The ID of a user
+ # key (required) - New SSH Key
+ # title (required) - New SSH Key's title
+ # Example Request:
+ # POST /users/:id/keys
+ post ":id/keys" do
+ authenticated_as_admin!
+ user = User.find(params[:id])
+ attrs = attributes_for_keys [:title, :key]
+ key = user.keys.new attrs
+ if key.save
+ present key, with: Entities::SSHKey
+ else
+ not_found!
+ end
+ end
+
# Delete user. Available only for admin
#
# Example Request:
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index fd0050cfd5f..66b2f450545 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -105,12 +105,6 @@ module ExtractsPath
# Automatically renders `not_found!` if a valid tree path could not be
# resolved (e.g., when a user inserts an invalid path or ref).
def assign_ref_vars
- # Handle formats embedded in the id
- if params[:id].ends_with?('.atom')
- params[:id].gsub!(/\.atom$/, '')
- request.format = :atom
- end
-
path = CGI::unescape(request.fullpath.dup)
@ref, @path = extract_ref(path)
diff --git a/lib/tasks/gitlab/setup.rake b/lib/tasks/gitlab/setup.rake
index 8d4950cf396..5b74daf956e 100644
--- a/lib/tasks/gitlab/setup.rake
+++ b/lib/tasks/gitlab/setup.rake
@@ -7,10 +7,12 @@ namespace :gitlab do
def setup_db
warn_user_is_not_gitlab
- puts "This will create the necessary database tables and seed the database."
- puts "You will lose any previous data stored in the database."
- ask_to_continue
- puts ""
+ unless ENV['force'] == 'yes'
+ puts "This will create the necessary database tables and seed the database."
+ puts "You will lose any previous data stored in the database."
+ ask_to_continue
+ puts ""
+ end
Rake::Task["db:setup"].invoke
Rake::Task["db:seed_fu"].invoke
diff --git a/spec/controllers/commits_controller_spec.rb b/spec/controllers/commits_controller_spec.rb
index 1d5d99df802..99cbcd13d56 100644
--- a/spec/controllers/commits_controller_spec.rb
+++ b/spec/controllers/commits_controller_spec.rb
@@ -13,7 +13,7 @@ describe CommitsController do
describe "GET show" do
context "as atom feed" do
it "should render as atom" do
- get :show, project_id: project.path, id: "master.atom"
+ get :show, project_id: project.path, id: "master", format: "atom"
response.should be_success
response.content_type.should == 'application/atom+xml'
end
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index df658a8cb07..e97ceb2c991 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -100,4 +100,27 @@ describe Gitlab::API do
end
end
end
+
+ describe "POST /groups/:id/projects/:project_id" do
+ let(:project) { create(:project) }
+ before(:each) do
+ project.stub!(:transfer).and_return(true)
+ Project.stub(:find).and_return(project)
+ end
+
+
+ context "when authenticated as user" do
+ it "should not transfer project to group" do
+ post api("/groups/#{group1.id}/projects/#{project.id}", user2)
+ response.status.should == 403
+ end
+ end
+
+ context "when authenticated as admin" do
+ it "should transfer project to group" do
+ project.should_receive(:transfer)
+ post api("/groups/#{group1.id}/projects/#{project.id}", admin)
+ end
+ end
+ end
end
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index 92ac5befc3a..901640834f2 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -105,13 +105,6 @@ describe Gitlab::API do
response.status.should == 404
end
end
-
- context "when notable is invalid" do
- it "should return a 404 error" do
- get api("/projects/#{project.id}/unknown/#{snippet.id}/notes", user)
- response.status.should == 404
- end
- end
end
describe "GET /projects/:id/noteable/:noteable_id/notes/:note_id" do
@@ -180,12 +173,5 @@ describe Gitlab::API do
response.status.should == 401
end
end
-
- context "when noteable is invalid" do
- it "should return a 404 error" do
- post api("/projects/#{project.id}/invalid/#{snippet.id}/notes", user)
- response.status.should == 404
- end
- end
end
end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 994c8d5ef2c..cddb7264018 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -6,11 +6,14 @@ describe Gitlab::API do
let(:user) { create(:user) }
let(:user2) { create(:user) }
let(:user3) { create(:user) }
+ let(:admin) { create(:admin) }
let!(:project) { create(:project, namespace: user.namespace ) }
let!(:hook) { create(:project_hook, project: project, url: "http://example.com") }
let!(:snippet) { create(:snippet, author: user, project: project, title: 'example') }
let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
let!(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) }
+ let(:key) { create(:key, project: project) }
+
before { project.team << [user, :reporter] }
describe "GET /projects" do
@@ -103,6 +106,46 @@ describe Gitlab::API do
end
end
+ describe "POST /projects/user/:id" do
+ before { admin }
+
+ it "should create new project without path" do
+ expect { post api("/projects/user/#{user.id}", admin), name: 'foo' }.to change {Project.count}.by(1)
+ end
+
+ it "should not create new project without name" do
+ expect { post api("/projects/user/#{user.id}", admin) }.to_not change {Project.count}
+ end
+
+ it "should respond with 201 on success" do
+ post api("/projects/user/#{user.id}", admin), name: 'foo'
+ response.status.should == 201
+ end
+
+ it "should respond with 404 on failure" do
+ post api("/projects/user/#{user.id}", admin)
+ response.status.should == 404
+ end
+
+ it "should assign attributes to project" do
+ project = attributes_for(:project, {
+ description: Faker::Lorem.sentence,
+ default_branch: 'stable',
+ issues_enabled: false,
+ wall_enabled: false,
+ merge_requests_enabled: false,
+ wiki_enabled: false
+ })
+
+ post api("/projects/user/#{user.id}", admin), project
+
+ project.each_pair do |k,v|
+ next if k == :path
+ json_response[k.to_s].should == v
+ end
+ end
+ end
+
describe "GET /projects/:id" do
it "should return a project by id" do
get api("/projects/#{project.id}", user)
@@ -591,4 +634,59 @@ describe Gitlab::API do
response.status.should == 400
end
end
+
+ describe "GET /projects/:id/keys" do
+ it "should return array of ssh keys" do
+ project.deploy_keys << key
+ project.save
+ get api("/projects/#{project.id}/keys", user)
+ response.status.should == 200
+ json_response.should be_an Array
+ json_response.first['title'].should == key.title
+ end
+ end
+
+ describe "GET /projects/:id/keys/:key_id" do
+ it "should return a single key" do
+ project.deploy_keys << key
+ project.save
+ get api("/projects/#{project.id}/keys/#{key.id}", user)
+ response.status.should == 200
+ json_response['title'].should == key.title
+ end
+
+ it "should return 404 Not Found with invalid ID" do
+ get api("/projects/#{project.id}/keys/404", user)
+ response.status.should == 404
+ end
+ end
+
+ describe "POST /projects/:id/keys" do
+ it "should not create an invalid ssh key" do
+ post api("/projects/#{project.id}/keys", user), { title: "invalid key" }
+ response.status.should == 404
+ end
+
+ it "should create new ssh key" do
+ key_attrs = attributes_for :key
+ expect {
+ post api("/projects/#{project.id}/keys", user), key_attrs
+ }.to change{ project.deploy_keys.count }.by(1)
+ end
+ end
+
+ describe "DELETE /projects/:id/keys/:key_id" do
+ it "should delete existing key" do
+ project.deploy_keys << key
+ project.save
+ expect {
+ delete api("/projects/#{project.id}/keys/#{key.id}", user)
+ }.to change{ project.deploy_keys.count }.by(-1)
+ end
+
+ it "should return 404 Not Found with invalid ID" do
+ delete api("/projects/#{project.id}/keys/404", user)
+ response.status.should == 404
+ end
+ end
end
diff --git a/spec/requests/api/system_hooks_spec.rb b/spec/requests/api/system_hooks_spec.rb
new file mode 100644
index 00000000000..9842ae91ec3
--- /dev/null
+++ b/spec/requests/api/system_hooks_spec.rb
@@ -0,0 +1,69 @@
+require 'spec_helper'
+
+describe Gitlab::API do
+ include ApiHelpers
+
+ let(:user) { create(:user) }
+ let(:admin) { create(:admin) }
+ let!(:hook) { create(:system_hook, url: "http://example.com") }
+
+ before { stub_request(:post, hook.url) }
+
+ describe "GET /hooks" do
+ context "when not an admin" do
+ it "should return forbidden error" do
+ get api("/hooks", user)
+ response.status.should == 403
+ end
+ end
+
+ context "when authenticated as admin" do
+ it "should return an array of hooks" do
+ get api("/hooks", admin)
+ response.status.should == 200
+ json_response.should be_an Array
+ json_response.first['url'].should == hook.url
+ end
+ end
+ end
+
+ describe "POST /hooks" do
+ it "should create new hook" do
+ expect {
+ post api("/hooks", admin), url: 'http://example.com'
+ }.to change { SystemHook.count }.by(1)
+ end
+
+ it "should respond with 404 on failure" do
+ post api("/hooks", admin)
+ response.status.should == 404
+ end
+
+ it "should not create new hook without url" do
+ expect {
+ post api("/hooks", admin)
+ }.to_not change { SystemHook.count }
+ end
+ end
+
+ describe "GET /hooks/:id" do
+ it "should return hook by id" do
+ get api("/hooks/#{hook.id}", admin)
+ response.status.should == 200
+ json_response['event_name'].should == 'project_create'
+ end
+
+ it "should return 404 on failure" do
+ get api("/hooks/404", admin)
+ response.status.should == 404
+ end
+ end
+
+ describe "DELETE /hooks/:id" do
+ it "should delete a hook" do
+ expect {
+ delete api("/hooks/#{hook.id}", admin)
+ }.to change { SystemHook.count }.by(-1)
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 25ce2d2fc3d..c2c9f8465b8 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -167,6 +167,22 @@ describe Gitlab::API do
end
end
+ describe "POST /users/:id/keys" do
+ before { admin }
+
+ it "should not create invalid ssh key" do
+ post api("/users/#{user.id}/keys", admin), { title: "invalid key" }
+ response.status.should == 404
+ end
+
+ it "should create ssh key" do
+ key_attrs = attributes_for :key
+ expect {
+ post api("/users/#{user.id}/keys", admin), key_attrs
+ }.to change{ user.keys.count }.by(1)
+ end
+ end
+
describe "DELETE /users/:id" do
before { admin }
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index 9cf5d91349f..986441494a5 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -56,7 +56,6 @@ end
# projects POST /projects(.:format) projects#create
# new_project GET /projects/new(.:format) projects#new
# wall_project GET /:id/wall(.:format) projects#wall
-# graph_project GET /:id/graph(.:format) projects#graph
# files_project GET /:id/files(.:format) projects#files
# edit_project GET /:id/edit(.:format) projects#edit
# project GET /:id(.:format) projects#show
@@ -75,10 +74,6 @@ describe ProjectsController, "routing" do
get("/gitlabhq/wall").should route_to('projects#wall', id: 'gitlabhq')
end
- it "to #graph" do
- get("/gitlabhq/graph/master").should route_to('graph#show', project_id: 'gitlabhq', id: 'master')
- end
-
it "to #files" do
get("/gitlabhq/files").should route_to('projects#files', id: 'gitlabhq')
end
@@ -202,6 +197,7 @@ describe RefsController, "routing" do
it "to #logs_tree" do
get("/gitlabhq/refs/stable/logs_tree").should route_to('refs#logs_tree', project_id: 'gitlabhq', id: 'stable')
get("/gitlabhq/refs/stable/logs_tree/foo/bar/baz").should route_to('refs#logs_tree', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz')
+ get("/gitlab/gitlabhq/refs/stable/logs_tree/files.scss").should route_to('refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable', path: 'files.scss')
end
end
@@ -301,6 +297,10 @@ describe CommitsController, "routing" do
let(:actions) { [:show] }
let(:controller) { 'commits' }
end
+
+ it "to #show" do
+ get("/gitlab/gitlabhq/commits/master.atom").should route_to('commits#show', project_id: 'gitlab/gitlabhq', id: "master", format: "atom")
+ end
end
# project_team_members GET /:project_id/team_members(.:format) team_members#index
@@ -385,6 +385,7 @@ end
describe BlameController, "routing" do
it "to #show" do
get("/gitlabhq/blame/master/app/models/project.rb").should route_to('blame#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
+ get("/gitlab/gitlabhq/blame/master/files.scss").should route_to('blame#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
end
end
@@ -393,6 +394,7 @@ describe BlobController, "routing" do
it "to #show" do
get("/gitlabhq/blob/master/app/models/project.rb").should route_to('blob#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
get("/gitlabhq/blob/master/app/models/compare.rb").should route_to('blob#show', project_id: 'gitlabhq', id: 'master/app/models/compare.rb')
+ get("/gitlab/gitlabhq/blob/master/files.scss").should route_to('blob#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
end
end
@@ -400,6 +402,7 @@ end
describe TreeController, "routing" do
it "to #show" do
get("/gitlabhq/tree/master/app/models/project.rb").should route_to('tree#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
+ get("/gitlab/gitlabhq/tree/master/files.scss").should route_to('tree#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
end
end
@@ -420,3 +423,10 @@ describe CompareController, "routing" do
get("/gitlabhq/compare/issue/1234...stable").should route_to('compare#show', project_id: 'gitlabhq', from: 'issue/1234', to: 'stable')
end
end
+
+describe GraphController, "routing" do
+ it "to #show" do
+ get("/gitlabhq/graph/master").should route_to('graph#show', project_id: 'gitlabhq', id: 'master')
+ get("/gitlabhq/graph/master.json").should route_to('graph#show', project_id: 'gitlabhq', id: 'master', format: "json")
+ end
+end
diff --git a/spec/support/stubbed_repository.rb b/spec/support/stubbed_repository.rb
index 106cfa6d55f..5fd8631a335 100644
--- a/spec/support/stubbed_repository.rb
+++ b/spec/support/stubbed_repository.rb
@@ -43,6 +43,11 @@ class GitLabTestRepo < Repository
def repo
@repo ||= Grit::Repo.new(Rails.root.join('tmp', 'repositories', 'gitlabhq'))
end
+
+ # patch repo size (in mb)
+ def size
+ 12.45
+ end
end
module Gitlab