summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormiks <miks@cubesystems.lv>2012-09-10 16:47:31 +0300
committermiks <miks@cubesystems.lv>2012-09-10 16:47:31 +0300
commit2e34a6d3c40a60ed689de5d7870fe663b1959e88 (patch)
treed2c1d12930948c11e2c767e8688ee49ac8c79ea4
parentfdb5c82c331e43dc5d0466d2a4c90ce3e649fc7b (diff)
parent8674fba173e520a67d60e6b5289dcd1bd648d537 (diff)
downloadgitlab-ce-2e34a6d3c40a60ed689de5d7870fe663b1959e88.tar.gz
Merge branch 'master' into project_hooks_api
-rw-r--r--Gemfile22
-rw-r--r--Gemfile.lock27
-rw-r--r--Guardfile30
-rw-r--r--app/assets/javascripts/issues.js4
-rw-r--r--app/assets/javascripts/main.js130
-rw-r--r--app/assets/javascripts/main.js.coffee92
-rw-r--r--app/assets/javascripts/note.js8
-rw-r--r--app/assets/javascripts/projects.js.coffee2
-rw-r--r--app/assets/stylesheets/common.scss9
-rw-r--r--app/controllers/refs_controller.rb2
-rw-r--r--app/decorators/event_decorator.rb4
-rw-r--r--app/helpers/projects_helper.rb4
-rw-r--r--app/helpers/tree_helper.rb10
-rw-r--r--app/models/event.rb20
-rw-r--r--app/models/merge_request.rb2
-rw-r--r--app/models/users_project.rb2
-rw-r--r--app/observers/users_project_observer.rb15
-rw-r--r--app/roles/push_event.rb2
-rw-r--r--app/views/admin/projects/_form.html.haml3
-rw-r--r--app/views/admin/projects/show.html.haml18
-rw-r--r--app/views/admin/team_members/_form.html.haml13
-rw-r--r--app/views/admin/users/show.html.haml18
-rw-r--r--app/views/commits/_head.html.haml7
-rw-r--r--app/views/devise/sessions/_new_ldap.html.haml2
-rw-r--r--app/views/events/_event.html.haml4
-rw-r--r--app/views/events/_event_membership_changed.html.haml9
-rw-r--r--app/views/issues/_form.html.haml4
-rw-r--r--app/views/issues/edit.html.haml7
-rw-r--r--app/views/issues/new.html.haml7
-rw-r--r--app/views/layouts/_head_panel.html.haml8
-rw-r--r--app/views/merge_requests/_form.html.haml15
-rw-r--r--app/views/milestones/_form.html.haml2
-rw-r--r--app/views/milestones/edit.html.haml6
-rw-r--r--app/views/projects/_refs.html.haml7
-rw-r--r--app/views/protected_branches/index.html.haml5
-rw-r--r--app/views/refs/_head.html.haml2
-rw-r--r--app/views/refs/_tree.html.haml9
-rw-r--r--app/views/refs/_tree_file.html.haml5
-rw-r--r--app/views/refs/blame.html.haml5
-rw-r--r--app/views/snippets/_form.html.haml10
-rw-r--r--app/views/team_members/_form.html.haml13
-rw-r--r--app/views/team_members/_show.html.haml20
-rw-r--r--config/gitlab.yml.example5
-rw-r--r--config/initializers/1_settings.rb4
-rw-r--r--doc/installation.md15
-rw-r--r--features/dashboard/dashboard.feature10
-rw-r--r--features/step_definitions/dashboard_steps.rb25
-rw-r--r--lib/api/helpers.rb45
-rw-r--r--lib/api/issues.rb8
-rw-r--r--lib/api/milestones.rb6
-rw-r--r--lib/api/projects.rb17
-rw-r--r--lib/gitlab/backend/gitolite.rb2
-rw-r--r--lib/gitlab/backend/gitolite_config.rb13
-rw-r--r--lib/gitlab/merge.rb3
-rw-r--r--spec/helpers/tree_helper_spec.rb15
-rw-r--r--spec/models/event_spec.rb22
-rw-r--r--spec/observers/users_project_observer_spec.rb27
-rw-r--r--spec/requests/api/projects_spec.rb2
58 files changed, 468 insertions, 335 deletions
diff --git a/Gemfile b/Gemfile
index b0724fadf5b..6205594a6aa 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,5 +1,13 @@
source "http://rubygems.org"
+def darwin_only(require_as)
+ RUBY_PLATFORM.include?('darwin') && require_as
+end
+
+def linux_only(require_as)
+ RUBY_PLATFORM.include?('linux') && require_as
+end
+
gem "rails", "3.2.8"
# Supported DBs
@@ -44,7 +52,8 @@ gem "ffaker"
gem "seed-fu"
# Markdown to HTML
-gem "redcarpet", "~> 2.1.1"
+gem "redcarpet", "~> 2.1.1"
+gem "github-markup", "~> 0.7.4"
# Servers
gem "thin"
@@ -101,13 +110,20 @@ group :development, :test do
gem "capybara"
gem "capybara-webkit"
gem "headless"
- gem "autotest"
- gem "autotest-rails"
gem "pry"
gem "awesome_print"
gem "database_cleaner"
gem "launchy"
gem 'factory_girl_rails'
+
+ # Guard
+ gem 'guard-rspec'
+ gem 'guard-cucumber'
+
+ # Notification
+ gem 'rb-fsevent', :require => darwin_only('rb-fsevent')
+ gem 'growl', :require => darwin_only('growl')
+ gem 'rb-inotify', :require => linux_only('rb-inotify')
end
group :test do
diff --git a/Gemfile.lock b/Gemfile.lock
index d0b6a53a096..94b162810b8 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -68,7 +68,6 @@ GIT
GEM
remote: http://rubygems.org/
specs:
- ZenTest (4.8.1)
actionmailer (3.2.8)
actionpack (= 3.2.8)
mail (~> 2.4.4)
@@ -100,10 +99,6 @@ GEM
rails (~> 3.0)
addressable (2.2.8)
arel (3.0.2)
- autotest (4.4.6)
- ZenTest (>= 4.4.1)
- autotest-rails (4.1.2)
- ZenTest (~> 4.5)
awesome_print (1.0.2)
bcrypt-ruby (3.0.1)
blankslate (2.1.2.4)
@@ -178,6 +173,7 @@ GEM
gherkin (2.11.0)
json (>= 1.4.6)
git (1.2.5)
+ github-markup (0.7.4)
gitlab_meta (2.9)
grape (0.2.1)
hashie (~> 1.2)
@@ -185,6 +181,15 @@ GEM
multi_xml
rack
rack-mount
+ growl (1.0.3)
+ guard (1.3.2)
+ listen (>= 0.4.2)
+ thor (>= 0.14.6)
+ guard-cucumber (1.2.0)
+ cucumber (>= 1.2.0)
+ guard (>= 1.1.0)
+ guard-rspec (1.2.1)
+ guard (>= 1.1)
haml (3.1.6)
haml-rails (0.3.4)
actionpack (~> 3.0)
@@ -218,6 +223,7 @@ GEM
libv8 (3.3.10.4)
libwebsocket (0.1.3)
addressable
+ listen (0.5.0)
mail (2.4.4)
i18n (>= 0.4.0)
mime-types (~> 1.16)
@@ -273,6 +279,9 @@ GEM
raindrops (0.9.0)
rake (0.9.2.2)
raphael-rails (1.5.2)
+ rb-fsevent (0.9.1)
+ rb-inotify (0.8.8)
+ ffi (>= 0.5.0)
rdoc (3.12)
json (~> 1.4)
redcarpet (2.1.1)
@@ -376,8 +385,6 @@ PLATFORMS
DEPENDENCIES
acts-as-taggable-on (= 2.3.1)
annotate!
- autotest
- autotest-rails
awesome_print
bootstrap-sass (= 2.0.4)
capybara
@@ -396,11 +403,15 @@ DEPENDENCIES
ffaker
foreman
git
+ github-markup (~> 0.7.4)
gitlab_meta (= 2.9)
gitolite!
grack!
grape (~> 0.2.1)
grit!
+ growl
+ guard-cucumber
+ guard-rspec
haml-rails
headless
httparty
@@ -418,6 +429,8 @@ DEPENDENCIES
rack-mini-profiler
rails (= 3.2.8)
raphael-rails (= 1.5.2)
+ rb-fsevent
+ rb-inotify
redcarpet (~> 2.1.1)
resque (~> 1.20.0)
resque_mailer
diff --git a/Guardfile b/Guardfile
new file mode 100644
index 00000000000..ed38f548d6e
--- /dev/null
+++ b/Guardfile
@@ -0,0 +1,30 @@
+# A sample Guardfile
+# More info at https://github.com/guard/guard#readme
+
+guard 'rspec', :version => 2 do
+ watch(%r{^spec/.+_spec\.rb$})
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
+ watch('spec/spec_helper.rb') { "spec" }
+
+ # Rails example
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
+ watch('config/routes.rb') { "spec/routing" }
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
+
+ # Capybara request specs
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
+
+ # Turnip features and steps
+ watch(%r{^spec/acceptance/(.+)\.feature$})
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
+end
+
+
+guard 'cucumber' do
+ watch(%r{^features/.+\.feature$})
+ watch(%r{^features/support/.+$}) { 'features' }
+ watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
+end
diff --git a/app/assets/javascripts/issues.js b/app/assets/javascripts/issues.js
index 148dc7b96e9..3ddc6926ecd 100644
--- a/app/assets/javascripts/issues.js
+++ b/app/assets/javascripts/issues.js
@@ -5,7 +5,7 @@ function switchToNewIssue(form){
$('select#issue_milestone_id').chosen();
$("#new_issue_dialog").show("fade", { direction: "right" }, 150);
$('.top-tabs .add_new').hide();
- disableButtonIfEmtpyField("#issue_title", ".save-btn");
+ disableButtonIfEmptyField("#issue_title", ".save-btn");
});
}
@@ -16,7 +16,7 @@ function switchToEditIssue(form){
$('select#issue_milestone_id').chosen();
$("#edit_issue_dialog").show("fade", { direction: "right" }, 150);
$('.add_new').hide();
- disableButtonIfEmtpyField("#issue_title", ".save-btn");
+ disableButtonIfEmptyField("#issue_title", ".save-btn");
});
}
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
deleted file mode 100644
index 61af1dc3d19..00000000000
--- a/app/assets/javascripts/main.js
+++ /dev/null
@@ -1,130 +0,0 @@
-$(document).ready(function(){
-
- $(".one_click_select").live("click", function(){
- $(this).select();
- });
-
- $('body').on('ajax:complete, ajax:beforeSend, submit', 'form', function(e){
- var buttons = $('[type="submit"]', this);
- switch( e.type ){
- case 'ajax:beforeSend':
- case 'submit':
- buttons.attr('disabled', 'disabled');
- break;
- case ' ajax:complete':
- default:
- buttons.removeAttr('disabled');
- break;
- }
- })
-
- $(".account-box").mouseenter(showMenu);
- $(".account-box").mouseleave(resetMenu);
-
- $("#projects-list .project").live('click', function(e){
- if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") {
- location.href = $(this).attr("url");
- e.stopPropagation();
- return false;
- }
- });
-
- /**
- * Focus search field by pressing 's' key
- */
- $(document).keypress(function(e) {
- if( $(e.target).is(":input") ) return;
- switch(e.which) {
- case 115: focusSearch();
- e.preventDefault();
- }
- });
-
- /**
- * Commit show suppressed diff
- *
- */
- $(".supp_diff_link").bind("click", function() {
- showDiff(this);
- });
-
- /**
- * Note markdown preview
- *
- */
- $(document).on('click', '#preview-link', function(e) {
- $('#preview-note').text('Loading...');
-
- var previewLinkText = ($(this).text() == 'Preview' ? 'Edit' : 'Preview');
- $(this).text(previewLinkText);
-
- var note = $('#note_note').val();
- if (note.trim().length === 0) { note = 'Nothing to preview'; }
- $.post($(this).attr('href'), {note: note}, function(data) {
- $('#preview-note').html(data);
- });
-
- $('#preview-note, #note_note').toggle();
- e.preventDefault();
- });
-});
-
-function focusSearch() {
- $("#search").focus();
-}
-
-function updatePage(data){
- $.ajax({type: "GET", url: location.href, data: data, dataType: "script"});
-}
-
-function showMenu() {
- $(this).toggleClass('hover');
-}
-
-function resetMenu() {
- $(this).removeClass("hover");
-}
-
-function slugify(text) {
- return text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase();
-}
-
-function showDiff(link) {
- $(link).next('table').show();
- $(link).remove();
-}
-
-(function($){
- var _chosen = $.fn.chosen;
- $.fn.extend({
- chosen: function(options) {
- var default_options = {'search_contains' : 'true'};
- $.extend(default_options, options);
- return _chosen.apply(this, [default_options]);
- }})
-})(jQuery);
-
-
-function ajaxGet(url) {
- $.ajax({type: "GET", url: url, dataType: "script"});
-}
-
-/**
- * Disable button if text field is empty
- */
-function disableButtonIfEmtpyField(field_selector, button_selector) {
- field = $(field_selector);
- if(field.val() == "") {
- field.closest("form").find(button_selector).attr("disabled", "disabled").addClass("disabled");
- }
-
- field.on('keyup', function(){
- var field = $(this);
- var closest_submit = field.closest("form").find(button_selector);
- if(field.val() == "") {
- closest_submit.attr("disabled", "disabled").addClass("disabled");
- } else {
- closest_submit.removeAttr("disabled").removeClass("disabled");
- }
- })
-}
diff --git a/app/assets/javascripts/main.js.coffee b/app/assets/javascripts/main.js.coffee
new file mode 100644
index 00000000000..86b191626b3
--- /dev/null
+++ b/app/assets/javascripts/main.js.coffee
@@ -0,0 +1,92 @@
+window.updatePage = (data) ->
+ $.ajax({type: "GET", url: location.href, data: data, dataType: "script"})
+
+window.slugify = (text) ->
+ text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
+
+window.ajaxGet = (url) ->
+ $.ajax({type: "GET", url: url, dataType: "script"})
+
+ # Disable button if text field is empty
+window.disableButtonIfEmptyField = (field_selector, button_selector) ->
+ field = $(field_selector)
+ closest_submit = field.closest("form").find(button_selector)
+
+ closest_submit.disable() if field.val() is ""
+
+ field.on "keyup", ->
+ if $(this).val() is ""
+ closest_submit.disable()
+ else
+ closest_submit.enable()
+
+$ ->
+ # Click a .one_click_select field, select the contents
+ $(".one_click_select").live 'click', -> $(this).select()
+
+ # Initialize chosen selects
+ $('select.chosen').chosen()
+
+ # Disable form buttons while a form is submitting
+ $('body').on 'ajax:complete, ajax:beforeSend, submit', 'form', (e) ->
+ buttons = $('[type="submit"]', this)
+
+ switch e.type
+ when 'ajax:beforeSend', 'submit'
+ buttons.disable()
+ else
+ buttons.enable()
+
+ # Show/Hide the profile menu when hovering the account box
+ $('.account-box').hover -> $(this).toggleClass('hover')
+
+ # Focus search field by pressing 's' key
+ $(document).keypress (e) ->
+ # Don't do anything if typing in an input
+ return if $(e.target).is(":input")
+
+ switch e.which
+ when 115
+ $("#search").focus()
+ e.preventDefault()
+
+ # Commit show suppressed diff
+ $(".supp_diff_link").bind "click", ->
+ $(this).next('table').show()
+ $(this).remove()
+
+ # Note markdown preview
+ $(document).on 'click', '#preview-link', (e) ->
+ $('#preview-note').text('Loading...')
+
+ previewLinkText = if $(this).text() == 'Preview' then 'Edit' else 'Preview'
+ $(this).text(previewLinkText)
+
+ note = $('#note_note').val()
+
+ if note.trim().length == 0
+ $('#preview-note').text("Nothing to preview.")
+ else
+ $.post $(this).attr('href'), {note: note}, (data) ->
+ $('#preview-note').html(data)
+
+ $('#preview-note, #note_note').toggle()
+ e.preventDefault()
+ false
+
+(($) ->
+ _chosen = $.fn.chosen
+ $.fn.extend chosen: (options) ->
+ default_options = search_contains: "true"
+ $.extend default_options, options
+ _chosen.apply this, [default_options]
+
+ # Disable an element and add the 'disabled' Bootstrap class
+ $.fn.extend disable: ->
+ $(this).attr('disabled', 'disabled').addClass('disabled')
+
+ # Enable an element and remove the 'disabled' Bootstrap class
+ $.fn.extend enable: ->
+ $(this).removeAttr('disabled').removeClass('disabled')
+
+)(jQuery)
diff --git a/app/assets/javascripts/note.js b/app/assets/javascripts/note.js
index 9cd3e36e87b..79ab086bfa2 100644
--- a/app/assets/javascripts/note.js
+++ b/app/assets/javascripts/note.js
@@ -25,14 +25,14 @@ var NoteList = {
$(this).closest('li').fadeOut(); });
$(".note-form-holder").live("ajax:before", function(){
- $(".submit_note").attr("disabled", "disabled");
+ $(".submit_note").disable()
})
$(".note-form-holder").live("ajax:complete", function(){
- $(".submit_note").removeAttr("disabled");
+ $(".submit_note").enable()
})
- disableButtonIfEmtpyField(".note-text", ".submit_note");
+ disableButtonIfEmptyField(".note-text", ".submit_note");
$(".note-text").live("focus", function(){
$(this).css("height", "80px");
@@ -177,6 +177,6 @@ var PerLineNotes = {
form.show();
return false;
});
- disableButtonIfEmtpyField(".line-note-text", ".submit_inline_note");
+ disableButtonIfEmptyField(".line-note-text", ".submit_inline_note");
}
}
diff --git a/app/assets/javascripts/projects.js.coffee b/app/assets/javascripts/projects.js.coffee
index 85ab2a06dff..14738e145e5 100644
--- a/app/assets/javascripts/projects.js.coffee
+++ b/app/assets/javascripts/projects.js.coffee
@@ -8,7 +8,7 @@ window.Projects = ->
$('.save-project-loader').show()
$('form #project_default_branch').chosen()
- disableButtonIfEmtpyField '#project_name', '.project-submit'
+ disableButtonIfEmptyField '#project_name', '.project-submit'
# Git clone panel switcher
$ ->
diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss
index aa27a280a18..6f69ba5abdc 100644
--- a/app/assets/stylesheets/common.scss
+++ b/app/assets/stylesheets/common.scss
@@ -179,6 +179,15 @@ span.update-author {
&.merged {
background-color: #2A2;
}
+
+ &.joined {
+ background-color: #1ca9dd;
+ }
+
+ &.left {
+ background-color: #888;
+ float:none;
+ }
}
form {
diff --git a/app/controllers/refs_controller.rb b/app/controllers/refs_controller.rb
index 3f81a2ca1a3..9036143779c 100644
--- a/app/controllers/refs_controller.rb
+++ b/app/controllers/refs_controller.rb
@@ -1,3 +1,5 @@
+require 'github/markup'
+
class RefsController < ApplicationController
include Gitlab::Encode
before_filter :project
diff --git a/app/decorators/event_decorator.rb b/app/decorators/event_decorator.rb
index 7df9081f045..ce0aaa039b9 100644
--- a/app/decorators/event_decorator.rb
+++ b/app/decorators/event_decorator.rb
@@ -8,7 +8,9 @@ class EventDecorator < ApplicationDecorator
"#{self.author_name} #{self.action_name} MR ##{self.target_id}:" + self.merge_request_title
elsif self.push?
"#{self.author_name} #{self.push_action_name} #{self.ref_type} " + self.ref_name
- else
+ elsif self.membership_changed?
+ "#{self.author_name} #{self.action_name} #{self.project.name}"
+ else
""
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 34dbb06cfb5..c7dc54ee93d 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -2,5 +2,9 @@ module ProjectsHelper
def grouper_project_members(project)
@project.users_projects.sort_by(&:project_access).reverse.group_by(&:project_access)
end
+
+ def remove_from_team_message(project, member)
+ "You are going to remove #{member.user_name} from #{project.name}. Are you sure?"
+ end
end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index ed3053d8af5..c51ee84a25e 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -24,4 +24,14 @@ module TreeHelper
content.name
end
end
+
+ # Public: Determines if a given filename is compatible with GitHub::Markup.
+ #
+ # filename - Filename string to check
+ #
+ # Returns boolean
+ def markup?(filename)
+ filename.end_with?(*%w(.mdown .md .markdown .textile .rdoc .org .creole
+ .mediawiki .rst .asciidoc .pod))
+ end
end
diff --git a/app/models/event.rb b/app/models/event.rb
index e20b79e2a82..308ffd63961 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -10,6 +10,8 @@ class Event < ActiveRecord::Base
Pushed = 5
Commented = 6
Merged = 7
+ Joined = 8 # User joined project
+ Left = 9 # User left project
belongs_to :project
belongs_to :target, polymorphic: true
@@ -37,7 +39,7 @@ class Event < ActiveRecord::Base
# - new issue
# - merge request
def allowed?
- push? || issue? || merge_request?
+ push? || issue? || merge_request? || membership_changed?
end
def push?
@@ -84,6 +86,18 @@ class Event < ActiveRecord::Base
[Closed, Reopened].include?(action)
end
+ def joined?
+ action == Joined
+ end
+
+ def left?
+ action == Left
+ end
+
+ def membership_changed?
+ joined? || left?
+ end
+
def issue
target if target_type == "Issue"
end
@@ -101,6 +115,10 @@ class Event < ActiveRecord::Base
"closed"
elsif merged?
"merged"
+ elsif joined?
+ 'joined'
+ elsif left?
+ 'left'
else
"opened"
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 542817b0eea..2e457f72286 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -162,7 +162,7 @@ class MergeRequest < ActiveRecord::Base
end
def automerge!(current_user)
- if Gitlab::Merge.new(self, current_user).merge
+ if Gitlab::Merge.new(self, current_user).merge && self.unmerged_commits.empty?
self.merge!(current_user.id)
true
end
diff --git a/app/models/users_project.rb b/app/models/users_project.rb
index 3b951f0dae9..ce64a10f3f0 100644
--- a/app/models/users_project.rb
+++ b/app/models/users_project.rb
@@ -23,7 +23,7 @@ class UsersProject < ActiveRecord::Base
def self.bulk_delete(project, user_ids)
UsersProject.transaction do
UsersProject.where(:user_id => user_ids, :project_id => project.id).each do |users_project|
- users_project.delete
+ users_project.destroy
end
end
end
diff --git a/app/observers/users_project_observer.rb b/app/observers/users_project_observer.rb
index 763b2c87f63..b2cea9f279e 100644
--- a/app/observers/users_project_observer.rb
+++ b/app/observers/users_project_observer.rb
@@ -1,9 +1,24 @@
class UsersProjectObserver < ActiveRecord::Observer
def after_create(users_project)
Notify.project_access_granted_email(users_project.id).deliver
+
+ Event.create(
+ project_id: users_project.project.id,
+ action: Event::Joined,
+ author_id: users_project.user.id
+ )
end
def after_update(users_project)
Notify.project_access_granted_email(users_project.id).deliver
end
+
+ def after_destroy(users_project)
+ Event.create(
+ project_id: users_project.project.id,
+ action: Event::Left,
+ author_id: users_project.user.id
+ )
+ end
+
end
diff --git a/app/roles/push_event.rb b/app/roles/push_event.rb
index ff8e28a2db2..a607f212f2a 100644
--- a/app/roles/push_event.rb
+++ b/app/roles/push_event.rb
@@ -90,6 +90,8 @@ module PushEvent
def push_with_commits?
md_ref? && commits.any? && parent_commit && last_commit
+ rescue Grit::NoSuchPathError
+ false
end
def last_push_to_non_root?
diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml
index 87d212e5710..4848e7391a3 100644
--- a/app/views/admin/projects/_form.html.haml
+++ b/app/views/admin/projects/_form.html.haml
@@ -32,7 +32,7 @@
- unless project.new_record?
.clearfix
= f.label :owner_id
- .input= f.select :owner_id, User.all.map { |user| [user.name, user.id] }
+ .input= f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
- if project.repo_exists?
.clearfix
@@ -69,7 +69,6 @@
:javascript
$(function(){
- $('#project_owner_id').chosen();
new Projects();
})
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 65d888f572b..639874109eb 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -71,25 +71,11 @@
%th Project Access:
%tr
- %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), multiple: true
- %td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select"
+ %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
+ %td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"}
%tr
%td= submit_tag 'Add', class: "btn primary"
%td
Read more about project permissions
%strong= link_to "here", help_permissions_path, class: "vlink"
-
-:css
- form select {
- width:150px;
- }
-
- #user_ids {
- width:300px;
- }
-
-:javascript
- $('select#user_ids').chosen();
- $('select#repo_access').chosen();
- $('select#project_access').chosen();
diff --git a/app/views/admin/team_members/_form.html.haml b/app/views/admin/team_members/_form.html.haml
index 6a128de94b2..9cd94fdd30f 100644
--- a/app/views/admin/team_members/_form.html.haml
+++ b/app/views/admin/team_members/_form.html.haml
@@ -8,20 +8,9 @@
.clearfix
%label Project Access:
.input
- = f.select :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), {}, class: "project-access-select"
+ = f.select :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), {}, class: "project-access-select chosen span3"
%br
.actions
= f.submit 'Save', class: "btn primary"
= link_to 'Cancel', :back, class: "btn"
-
-:css
- form select {
- width:300px;
- }
-
-:javascript
- $('select#team_member_user_id').chosen();
- $('select#team_member_project_id').chosen();
- $('select#team_member_repo_access').chosen();
- $('select#team_member_project_access').chosen();
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 4d2b983277a..731916e97de 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -68,8 +68,8 @@
%th Project Access:
%tr
- %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name), multiple: true
- %td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select"
+ %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
+ %td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select chosen span3"
%tr
%td= submit_tag 'Add', class: "btn primary"
@@ -97,17 +97,3 @@
%td= select_tag :tm_project_access, options_for_select(Project.access_options, tm.project_access), class: "medium project-access-select", disabled: :disabled
%td= link_to 'Edit Access', edit_admin_team_member_path(tm), class: "btn small"
%td= link_to 'Remove from team', admin_team_member_path(tm), confirm: 'Are you sure?', method: :delete, class: "btn small danger"
-
-:css
- form select {
- width:150px;
- }
-
- #project_ids {
- width:300px;
- }
-
-:javascript
- $('select#project_ids').chosen();
- $('select#repo_access').chosen();
- $('select#project_access').chosen();
diff --git a/app/views/commits/_head.html.haml b/app/views/commits/_head.html.haml
index a211329f349..5a09d82aa61 100644
--- a/app/views/commits/_head.html.haml
+++ b/app/views/commits/_head.html.haml
@@ -1,7 +1,7 @@
%ul.nav.nav-tabs
%li
= form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form" do
- = select_tag "ref", grouped_options_refs, onchange: "$(this.form).trigger('submit');", class: "project-refs-select"
+ = select_tag "ref", grouped_options_refs, onchange: "$(this.form).trigger('submit');", class: "project-refs-select chosen"
= hidden_field_tag :destination, "commits"
%li{class: "#{'active' if current_page?(project_commits_path(@project)) }"}
@@ -26,8 +26,3 @@
%span.rss-icon
= link_to project_commits_path(@project, :atom, { private_token: current_user.private_token, ref: @ref }), title: "Feed" do
= image_tag "rss_ui.png", title: "feed"
-
-:javascript
- $(function(){
- $('.project-refs-select').chosen();
- });
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index 85010df7a8a..4233aa61ecb 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -15,7 +15,7 @@
$(function() {
$('#new_user').toggle();
});
- = form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "login-box" }) do |f|
+= form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "login-box" }) do |f|
= f.text_field :email, :class => "text top", :placeholder => "Email"
= f.password_field :password, :class => "text bottom", :placeholder => "Password"
- if devise_mapping.rememberable?
diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml
index d49f0382dea..7bae8db13f7 100644
--- a/app/views/events/_event.html.haml
+++ b/app/views/events/_event.html.haml
@@ -11,3 +11,7 @@
.event_feed
= render "events/event_push", event: event
+ - elsif event.membership_changed?
+ .event_feed
+ = render "events/event_membership_changed", event: event
+
diff --git a/app/views/events/_event_membership_changed.html.haml b/app/views/events/_event_membership_changed.html.haml
new file mode 100644
index 00000000000..b079c138f5a
--- /dev/null
+++ b/app/views/events/_event_membership_changed.html.haml
@@ -0,0 +1,9 @@
+= image_tag gravatar_icon(event.author_email), class: "avatar"
+%strong #{event.author_name}
+%span.event_label{class: event.action_name}= event.action_name
+project
+%strong= link_to event.project.name, event.project
+%span.cgray
+ = time_ago_in_words(event.created_at)
+ ago.
+
diff --git a/app/views/issues/_form.html.haml b/app/views/issues/_form.html.haml
index 23de7e8ed15..813ecab2d19 100644
--- a/app/views/issues/_form.html.haml
+++ b/app/views/issues/_form.html.haml
@@ -18,12 +18,12 @@
= f.label :assignee_id do
%i.icon-user
Assign to
- .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select a user" })
+ .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select a user" }, {class: 'chosen'})
.issue_milestone
= f.label :milestone_id do
%i.icon-time
Milestone
- .input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" })
+ .input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'})
.issue_description
.clearfix
diff --git a/app/views/issues/edit.html.haml b/app/views/issues/edit.html.haml
index 3c9877f842f..b1bc3ba0eba 100644
--- a/app/views/issues/edit.html.haml
+++ b/app/views/issues/edit.html.haml
@@ -1,8 +1 @@
= render "form"
-
-:javascript
- $(function(){
- $('select#issue_assignee_id').chosen();
- $('select#issue_milestone_id').chosen();
- });
-
diff --git a/app/views/issues/new.html.haml b/app/views/issues/new.html.haml
index 3c9877f842f..b1bc3ba0eba 100644
--- a/app/views/issues/new.html.haml
+++ b/app/views/issues/new.html.haml
@@ -1,8 +1 @@
= render "form"
-
-:javascript
- $(function(){
- $('select#issue_assignee_id').chosen();
- $('select#issue_milestone_id').chosen();
- });
-
diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml
index d6247d36b0d..f5e423a5abf 100644
--- a/app/views/layouts/_head_panel.html.haml
+++ b/app/views/layouts/_head_panel.html.haml
@@ -34,12 +34,4 @@
source: #{raw search_autocomplete_source},
select: function(event, ui) { location.href = ui.item.url }
});
-
- $(document).keypress(function(e) {
- if($(e.target).is(":input")) return;
- switch(e.which) {
- case 115: focusSearch();
- e.preventDefault();
- }
- });
});
diff --git a/app/views/merge_requests/_form.html.haml b/app/views/merge_requests/_form.html.haml
index b554c051964..96692c0f93d 100644
--- a/app/views/merge_requests/_form.html.haml
+++ b/app/views/merge_requests/_form.html.haml
@@ -16,7 +16,7 @@
.padded
= f.label :source_branch, "From", class: "control-label"
.controls
- = f.select(:source_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, style: "width:250px")
+ = f.select(:source_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span3'})
.mr_source_commit
.span2
@@ -28,7 +28,7 @@
.padded
= f.label :target_branch, "To", class: "control-label"
.controls
- = f.select(:target_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, style: "width:250px")
+ = f.select(:target_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span3'})
.mr_target_commit
%h4.cdark 2. Fill info
@@ -43,7 +43,7 @@
= f.label :assignee_id do
%i.icon-user
Assign to
- .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, style: "width:250px")
+ .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, {class: 'chosen span3'})
.control-group
@@ -56,18 +56,12 @@
= link_to project_merge_request_path(@project, @merge_request), class: "btn cancel-btn" do
Cancel
-
-
:javascript
$(function(){
- disableButtonIfEmtpyField("#merge_request_title", ".save-btn");
- $('select#merge_request_assignee_id').chosen();
- $('select#merge_request_source_branch').chosen();
- $('select#merge_request_target_branch').chosen();
+ disableButtonIfEmptyField("#merge_request_title", ".save-btn");
var source_branch = $("#merge_request_source_branch");
var target_branch = $("#merge_request_target_branch");
-
$.get("#{branch_from_project_merge_requests_path(@project)}", {ref: source_branch.val() });
$.get("#{branch_to_project_merge_requests_path(@project)}", {ref: target_branch.val() });
@@ -79,4 +73,3 @@
$.get("#{branch_to_project_merge_requests_path(@project)}", {ref: $(this).val() });
});
});
-
diff --git a/app/views/milestones/_form.html.haml b/app/views/milestones/_form.html.haml
index ce4145ba3e6..194eac7783c 100644
--- a/app/views/milestones/_form.html.haml
+++ b/app/views/milestones/_form.html.haml
@@ -41,7 +41,7 @@
:javascript
$(function() {
- disableButtonIfEmtpyField("#milestone_title", ".save-btn");
+ disableButtonIfEmptyField("#milestone_title", ".save-btn");
$( ".datepicker" ).datepicker({
dateFormat: "yy-mm-dd",
onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) }
diff --git a/app/views/milestones/edit.html.haml b/app/views/milestones/edit.html.haml
index af975a84a49..b1bc3ba0eba 100644
--- a/app/views/milestones/edit.html.haml
+++ b/app/views/milestones/edit.html.haml
@@ -1,7 +1 @@
= render "form"
-
-:javascript
- $(function(){
- $('select#issue_assignee_id').chosen();
- });
-
diff --git a/app/views/projects/_refs.html.haml b/app/views/projects/_refs.html.haml
index 804b852340e..dc1f3a282d8 100644
--- a/app/views/projects/_refs.html.haml
+++ b/app/views/projects/_refs.html.haml
@@ -1,8 +1,3 @@
= form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form" do
- = select_tag "ref", grouped_options_refs, onchange: "this.form.submit();", class: "project-refs-select"
+ = select_tag "ref", grouped_options_refs, onchange: "this.form.submit();", class: "project-refs-select chosen"
= hidden_field_tag :destination, destination
-
-:javascript
- $(function(){
- $('.project-refs-select').chosen();
- })
diff --git a/app/views/protected_branches/index.html.haml b/app/views/protected_branches/index.html.haml
index 33bb448a544..43884de1db5 100644
--- a/app/views/protected_branches/index.html.haml
+++ b/app/views/protected_branches/index.html.haml
@@ -19,7 +19,7 @@
.entry.clearfix
= f.label :name, "Branch"
.span3
- = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , { include_blank: "-- Select branch" }, { class: "span3" })
+ = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: "Select branch"}, {class: "chosen span3"})
&nbsp;
= f.submit 'Protect', class: "primary btn"
@@ -46,6 +46,3 @@
%td
- if can? current_user, :admin_project, @project
= link_to 'Unprotect', [@project, branch], confirm: 'Are you sure?', method: :delete, class: "danger btn small"
-
-:javascript
- $('select#protected_branch_name').chosen();
diff --git a/app/views/refs/_head.html.haml b/app/views/refs/_head.html.haml
index d51602de9b7..94603f0a42a 100644
--- a/app/views/refs/_head.html.haml
+++ b/app/views/refs/_head.html.haml
@@ -1,7 +1,7 @@
%ul.nav.nav-tabs
%li
= form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form", remote: true do
- = select_tag "ref", grouped_options_refs, onchange: "$(this.form).trigger('submit');", class: "project-refs-select"
+ = select_tag "ref", grouped_options_refs, onchange: "$(this.form).trigger('submit');", class: "project-refs-select chosen"
= hidden_field_tag :destination, "tree"
= hidden_field_tag :path, params[:path]
%li{class: "#{'active' if (controller.controller_name == "refs") }"}
diff --git a/app/views/refs/_tree.html.haml b/app/views/refs/_tree.html.haml
index a4765c1087a..83e73280666 100644
--- a/app/views/refs/_tree.html.haml
+++ b/app/views/refs/_tree.html.haml
@@ -43,18 +43,11 @@
%i.icon-file
= content.name
.file_content.wiki
- - if content.name =~ /\.(md|markdown)$/i
- = preserve do
- = markdown(content.data)
- - else
- = simple_format(content.data)
+ = raw GitHub::Markup.render(content.name, content.data)
:javascript
$(function(){
- $('.project-refs-select').chosen();
-
history.pushState({ path: this.path }, '', "#{@history_path}");
-
});
// Load last commit log for each file in tree
diff --git a/app/views/refs/_tree_file.html.haml b/app/views/refs/_tree_file.html.haml
index b5ed61bb45a..765f271a1bf 100644
--- a/app/views/refs/_tree_file.html.haml
+++ b/app/views/refs/_tree_file.html.haml
@@ -9,10 +9,9 @@
= link_to "history", project_commits_path(@project, path: params[:path], ref: @ref), class: "btn very_small"
= link_to "blame", blame_file_project_ref_path(@project, @ref, path: params[:path]), class: "btn very_small"
- if file.text?
- - if name =~ /\.(md|markdown)$/i
+ - if markup?(name)
.file_content.wiki
- = preserve do
- = markdown(file.data)
+ = raw GitHub::Markup.render(name, file.data)
- else
.file_content.code
- unless file.empty?
diff --git a/app/views/refs/blame.html.haml b/app/views/refs/blame.html.haml
index 34478d4b491..eb66f59760b 100644
--- a/app/views/refs/blame.html.haml
+++ b/app/views/refs/blame.html.haml
@@ -38,8 +38,3 @@
= preserve do
%pre
= Gitlab::Encode.utf8 lines.join("\n")
-
-:javascript
- $(function(){
- $('.project-refs-select').chosen();
- });
diff --git a/app/views/snippets/_form.html.haml b/app/views/snippets/_form.html.haml
index b8d8c09849d..e61e61a7e5e 100644
--- a/app/views/snippets/_form.html.haml
+++ b/app/views/snippets/_form.html.haml
@@ -16,7 +16,7 @@
.input= f.text_field :file_name, placeholder: "example.rb"
.clearfix
= f.label "Lifetime"
- .input= f.select :expires_at, lifetime_select_options, {}, style: "width:200px;"
+ .input= f.select :expires_at, lifetime_select_options, {}, {class: 'chosen span2'}
.clearfix
= f.label :content, "Code"
.input= f.text_area :content, class: "span8"
@@ -26,11 +26,3 @@
= link_to "Cancel", project_snippets_path(@project), class: " btn"
- unless @snippet.new_record?
.right= link_to 'Destroy', [@project, @snippet], confirm: 'Are you sure?', method: :delete, class: "btn right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
-
-
-
-:javascript
- $(function(){
- $('select#snippet_expires_at').chosen();
- });
-
diff --git a/app/views/team_members/_form.html.haml b/app/views/team_members/_form.html.haml
index 192f273579e..3736bfea005 100644
--- a/app/views/team_members/_form.html.haml
+++ b/app/views/team_members/_form.html.haml
@@ -10,21 +10,14 @@
%h6 1. Choose people you want in the team
.clearfix
- = f.label :user_ids, "Peolpe"
- .input= select_tag(:user_ids, options_from_collection_for_select(User.not_in_project(@project).all, :id, :name), { class: "xxlarge", multiple: true })
-
+ = f.label :user_ids, "People"
+ .input= select_tag(:user_ids, options_from_collection_for_select(User.not_in_project(@project).all, :id, :name), {data: {placeholder: "Select users"}, class: "chosen xxlarge", multiple: true})
%h6 2. Set access level for them
.clearfix
= f.label :project_access, "Project Access"
- .input= select_tag :project_access, options_for_select(Project.access_options, @team_member.project_access), class: "project-access-select"
-
+ .input= select_tag :project_access, options_for_select(Project.access_options, @team_member.project_access), class: "project-access-select chosen"
.actions
= f.submit 'Save', class: "btn save-btn"
= link_to "Cancel", team_project_path(@project), class: "btn cancel-btn"
-
-
-:javascript
- $('select#user_ids').chosen();
- $('select#project_access').chosen();
diff --git a/app/views/team_members/_show.html.haml b/app/views/team_members/_show.html.haml
index d9a724944b8..f68f8eb471f 100644
--- a/app/views/team_members/_show.html.haml
+++ b/app/views/team_members/_show.html.haml
@@ -1,20 +1,26 @@
- user = member.user
- allow_admin = can? current_user, :admin_project, @project
%tr{id: dom_id(member), class: "team_member_row user_#{user.id}"}
- %td
+ %td.span6
= link_to project_team_member_path(@project, member), title: user.name, class: "dark" do
= image_tag gravatar_icon(user.email, 40), class: "avatar s32"
= link_to project_team_member_path(@project, member), title: user.name, class: "dark" do
%strong= truncate(user.name, lenght: 40)
- %br
- %div.cgray= user.email
+ %br
+ %small.cgray= user.email
- %td
+ %td.span5
.right
+ - if current_user == user
+ %span.btn.disabled This is you!
- if @project.owner == user
- %span.btn.disabled.success Project Owner
- - if user.blocked
+ %span.btn.disabled.success Owner
+ - elsif user.blocked
%span.btn.disabled.blocked Blocked
+ - elsif allow_admin
+ = link_to project_team_member_path(project_id: @project, id: member.id), confirm: remove_from_team_message(@project, member), method: :delete, class: "very_small btn danger" do
+ %i.icon-minus.icon-white
+
- if allow_admin
= form_for(member, as: :team_member, url: project_team_member_path(@project, member)) do |f|
- = f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, class: "medium project-access-select"
+ = f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, class: "medium project-access-select span2"
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index d05cc1bead6..08e3427f900 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -33,11 +33,12 @@ app:
git_host:
admin_uri: git@localhost:gitolite-admin
base_path: /home/git/repositories/
- # hooks_path: /var/lib/gitolite/.gitolite/hooks/ # only needed when gitolite is not installed according the manual
- # host: localhost
+ hooks_path: /home/git/.gitolite/hooks/
+ gitolite_admin_key: gitlab
git_user: git
upload_pack: true
receive_pack: true
+ # host: localhost
# port: 22
# Git settings
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 27c5bc2270c..df9ccf32194 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -102,6 +102,10 @@ class Settings < Settingslogic
git_host['admin_uri'] || 'git@localhost:gitolite-admin'
end
+ def gitolite_admin_key
+ git_host['gitolite_admin_key'] || 'gitlab'
+ end
+
def default_projects_limit
app['default_projects_limit'] || 10
end
diff --git a/doc/installation.md b/doc/installation.md
index e14ec711e7b..af169d81c6f 100644
--- a/doc/installation.md
+++ b/doc/installation.md
@@ -113,17 +113,20 @@ Generate key:
Clone GitLab's fork of the Gitolite source code:
cd /home/git
- sudo -H -u git git clone https://github.com/gitlabhq/gitolite.git /home/git/gitolite
+ sudo -H -u git git clone -b gl-v304 https://github.com/gitlabhq/gitolite.git /home/git/gitolite
Setup:
+ cd /home/git
+ sudo -u git -H mkdir bin
sudo -u git sh -c 'echo -e "PATH=\$PATH:/home/git/bin\nexport PATH" >> /home/git/.profile'
- sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; /home/git/gitolite/src/gl-system-install"
+ sudo -u git sh -c 'gitolite/install -ln /home/git/bin'
+
sudo cp /home/gitlab/.ssh/id_rsa.pub /home/git/gitlab.pub
sudo chmod 0444 /home/git/gitlab.pub
- sudo -u git -H sed -i 's/0077/0007/g' /home/git/share/gitolite/conf/example.gitolite.rc
- sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; gl-setup -q /home/git/gitlab.pub"
+ sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; gitolite setup -pk /home/git/gitlab.pub"
+ sudo -u git -H sed -i 's/0077/0007/g' /home/git/.gitolite.rc
Permissions:
@@ -189,8 +192,8 @@ and ensure you have followed all of the above steps carefully.
#### Setup GitLab hooks
- sudo cp ./lib/hooks/post-receive /home/git/share/gitolite/hooks/common/post-receive
- sudo chown git:git /home/git/share/gitolite/hooks/common/post-receive
+ sudo cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive
+ sudo chown git:git /home/git/.gitolite/hooks/common/post-receive
#### Check application status
diff --git a/features/dashboard/dashboard.feature b/features/dashboard/dashboard.feature
index a8c2205c143..98bb49803f3 100644
--- a/features/dashboard/dashboard.feature
+++ b/features/dashboard/dashboard.feature
@@ -15,4 +15,14 @@ Feature: Dashboard
And I click "Create Merge Request" link
Then I see prefilled new Merge Request page
+ Scenario: I should see User joined Project event
+ Given user with name "John Doe" joined project "Shop"
+ When I visit dashboard page
+ Then I should see "John Doe joined project Shop" event
+ Scenario: I should see User left Project event
+ Given user with name "John Doe" joined project "Shop"
+ And user with name "John Doe" left project "Shop"
+ When I visit dashboard page
+ Then I should see "John Doe left project Shop" event
+
diff --git a/features/step_definitions/dashboard_steps.rb b/features/step_definitions/dashboard_steps.rb
index 867233c82cb..3ddc68e931c 100644
--- a/features/step_definitions/dashboard_steps.rb
+++ b/features/step_definitions/dashboard_steps.rb
@@ -109,3 +109,28 @@ Given /^I have authored merge requests$/ do
:author => @user,
:project => project2
end
+
+Given /^user with name "(.*?)" joined project "(.*?)"$/ do |user_name, project_name|
+ user = Factory.create(:user, {name: user_name})
+ project = Project.find_by_name project_name
+ Event.create(
+ project: project,
+ author_id: user.id,
+ action: Event::Joined
+ )
+end
+
+Given /^user with name "(.*?)" left project "(.*?)"$/ do |user_name, project_name|
+ user = User.find_by_name user_name
+ project = Project.find_by_name project_name
+ Event.create(
+ project: project,
+ author_id: user.id,
+ action: Event::Left
+ )
+end
+
+Then /^I should see "(.*?)" event$/ do |event_text|
+ page.should have_content(event_text)
+end
+
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index ce7b7b497fc..054eb2d3f70 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -8,7 +8,7 @@ module Gitlab
if @project ||= current_user.projects.find_by_id(params[:id]) ||
current_user.projects.find_by_code(params[:id])
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
@project
@@ -19,7 +19,48 @@ module Gitlab
end
def authenticate!
- error!({'message' => '401 Unauthorized'}, 401) unless current_user
+ unauthorized! unless current_user
+ end
+
+ def authorize! action, subject
+ unless abilities.allowed?(current_user, action, subject)
+ forbidden!
+ end
+ end
+
+ # error helpers
+
+ def forbidden!
+ render_api_error!('403 Forbidden', 403)
+ end
+
+ def not_found!(resource = nil)
+ message = ["404"]
+ message << resource if resource
+ message << "Not Found"
+ render_api_error!(message.join(' '), 404)
+ end
+
+ def unauthorized!
+ render_api_error!('401 Unauthorized', 401)
+ end
+
+ def not_allowed!
+ render_api_error!('Method Not Allowed', 405)
+ end
+
+ def render_api_error!(message, status)
+ error!({'message' => message}, status)
+ end
+
+ private
+
+ def abilities
+ @abilities ||= begin
+ abilities = Six.new
+ abilities << Ability
+ abilities
+ end
end
end
end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 68cb7e059b9..659f065e390 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -60,7 +60,7 @@ module Gitlab
if @issue.save
present @issue, with: Entities::Issue
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
end
@@ -79,6 +79,8 @@ module Gitlab
# PUT /projects/:id/issues/:issue_id
put ":id/issues/:issue_id" do
@issue = user_project.issues.find(params[:issue_id])
+ authorize! :modify_issue, @issue
+
parameters = {
title: (params[:title] || @issue.title),
description: (params[:description] || @issue.description),
@@ -91,7 +93,7 @@ module Gitlab
if @issue.update_attributes(parameters)
present @issue, with: Entities::Issue
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
end
@@ -103,7 +105,7 @@ module Gitlab
# Example Request:
# DELETE /projects/:id/issues/:issue_id
delete ":id/issues/:issue_id" do
- error!({'message' => 'method not allowed'}, 405)
+ not_allowed!
end
end
end
diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb
index 29f5efa41d6..4b0424ba444 100644
--- a/lib/api/milestones.rb
+++ b/lib/api/milestones.rb
@@ -45,7 +45,7 @@ module Gitlab
if @milestone.save
present @milestone, with: Entities::Milestone
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
end
@@ -61,6 +61,8 @@ module Gitlab
# Example Request:
# PUT /projects/:id/milestones/:milestone_id
put ":id/milestones/:milestone_id" do
+ authorize! :admin_milestone, user_project
+
@milestone = user_project.milestones.find(params[:milestone_id])
parameters = {
title: (params[:title] || @milestone.title),
@@ -72,7 +74,7 @@ module Gitlab
if @milestone.update_attributes(parameters)
present @milestone, with: Entities::Milestone
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
end
end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 876de321c9c..dfdd359c2b2 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -50,7 +50,7 @@ module Gitlab
if @project.saved?
present @project, with: Entities::Project
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
end
@@ -74,6 +74,7 @@ module Gitlab
# Example Request:
# POST /projects/:id/users
post ":id/users" do
+ authorize! :admin_project, user_project
user_project.add_users_ids_to_team(params[:user_ids].values, params[:project_access])
nil
end
@@ -87,6 +88,7 @@ module Gitlab
# Example Request:
# PUT /projects/:id/add_users
put ":id/users" do
+ authorize! :admin_project, user_project
user_project.update_users_ids_to_role(params[:user_ids].values, params[:project_access])
nil
end
@@ -99,6 +101,7 @@ module Gitlab
# Example Request:
# DELETE /projects/:id/users
delete ":id/users" do
+ authorize! :admin_project, user_project
user_project.delete_users_ids_from_team(params[:user_ids].values)
nil
end
@@ -209,7 +212,7 @@ module Gitlab
if @snippet.save
present @snippet, with: Entities::ProjectSnippet
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
end
@@ -226,6 +229,8 @@ module Gitlab
# PUT /projects/:id/snippets/:snippet_id
put ":id/snippets/:snippet_id" do
@snippet = user_project.snippets.find(params[:snippet_id])
+ authorize! :modify_snippet, @snippet
+
parameters = {
title: (params[:title] || @snippet.title),
file_name: (params[:file_name] || @snippet.file_name),
@@ -236,7 +241,7 @@ module Gitlab
if @snippet.update_attributes(parameters)
present @snippet, with: Entities::ProjectSnippet
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
end
@@ -249,6 +254,8 @@ module Gitlab
# DELETE /projects/:id/snippets/:snippet_id
delete ":id/snippets/:snippet_id" do
@snippet = user_project.snippets.find(params[:snippet_id])
+ authorize! :modify_snippet, @snippet
+
@snippet.destroy
end
@@ -277,10 +284,10 @@ module Gitlab
ref = params[:sha]
commit = user_project.commit ref
- error!('404 Commit Not Found', 404) unless commit
+ not_found! "Commit" unless commit
tree = Tree.new commit.tree, user_project, ref, params[:filepath]
- error!('404 File Not Found', 404) unless tree.try(:tree)
+ not_found! "File" unless tree.try(:tree)
if tree.text?
encoding = Gitlab::Encode.detect_encoding(tree.data)
diff --git a/lib/gitlab/backend/gitolite.rb b/lib/gitlab/backend/gitolite.rb
index 658182c7858..fe5dcef40a9 100644
--- a/lib/gitlab/backend/gitolite.rb
+++ b/lib/gitlab/backend/gitolite.rb
@@ -35,7 +35,7 @@ module Gitlab
end
def enable_automerge
- config.admin_all_repo!(project)
+ config.admin_all_repo!
end
alias_method :create_repository, :update_repository
diff --git a/lib/gitlab/backend/gitolite_config.rb b/lib/gitlab/backend/gitolite_config.rb
index 61ec8c11cd7..0d636d2d789 100644
--- a/lib/gitlab/backend/gitolite_config.rb
+++ b/lib/gitlab/backend/gitolite_config.rb
@@ -148,18 +148,7 @@ module Gitlab
# Enable access to all repos for gitolite admin.
# We use it for accept merge request feature
def admin_all_repo
- owner_name = ""
-
- # Read gitolite-admin user
- #
- begin
- repo = conf.get_repo("gitolite-admin")
- owner_name = repo.permissions[0]["RW+"][""][0]
- raise StandardError if owner_name.blank?
- rescue => ex
- puts "Can't determine gitolite-admin owner".red
- raise StandardError
- end
+ owner_name = Gitlab.config.gitolite_admin_key
# @ALL repos premission for gitolite owner
repo_name = "@all"
diff --git a/lib/gitlab/merge.rb b/lib/gitlab/merge.rb
index 134695ce21c..180135745f8 100644
--- a/lib/gitlab/merge.rb
+++ b/lib/gitlab/merge.rb
@@ -21,8 +21,7 @@ module Gitlab
if output =~ /CONFLICT/
false
else
- repo.git.push({}, "origin", merge_request.target_branch)
- true
+ !!repo.git.push({}, "origin", merge_request.target_branch)
end
end
end
diff --git a/spec/helpers/tree_helper_spec.rb b/spec/helpers/tree_helper_spec.rb
new file mode 100644
index 00000000000..bb124d8b303
--- /dev/null
+++ b/spec/helpers/tree_helper_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe TreeHelper do
+ describe '#markup?' do
+ %w(mdown md markdown textile rdoc org creole mediawiki rst asciidoc pod).each do |type|
+ it "returns true for #{type} files" do
+ markup?("README.#{type}").should be_true
+ end
+ end
+
+ it "returns false when given a non-markup filename" do
+ markup?('README.rb').should_not be_true
+ end
+ end
+end
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index aaffda3199e..ee022e959e7 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -49,4 +49,26 @@ describe Event do
it { @event.branch_name.should == "master" }
it { @event.author.should == @user }
end
+
+ describe "Joined project team" do
+ let(:project) {Factory.create :project}
+ let(:new_user) {Factory.create :user}
+ it "should create event" do
+ UsersProject.observers.enable :users_project_observer
+ expect{
+ UsersProject.bulk_import(project, [new_user.id], UsersProject::DEVELOPER)
+ }.to change{Event.count}.by(1)
+ end
+ end
+ describe "Left project team" do
+ let(:project) {Factory.create :project}
+ let(:new_user) {Factory.create :user}
+ it "should create event" do
+ UsersProject.bulk_import(project, [new_user.id], UsersProject::DEVELOPER)
+ UsersProject.observers.enable :users_project_observer
+ expect{
+ UsersProject.bulk_delete(project, [new_user.id])
+ }.to change{Event.count}.by(1)
+ end
+ end
end
diff --git a/spec/observers/users_project_observer_spec.rb b/spec/observers/users_project_observer_spec.rb
index 3e3920407cb..f38d98620a3 100644
--- a/spec/observers/users_project_observer_spec.rb
+++ b/spec/observers/users_project_observer_spec.rb
@@ -23,6 +23,14 @@ describe UsersProjectObserver do
Notify.should_receive(:project_access_granted_email).with(users_project.id).and_return(double(deliver: true))
subject.after_create(users_project)
end
+ it "should create new event" do
+ Event.should_receive(:create).with(
+ project_id: users_project.project.id,
+ action: Event::Joined,
+ author_id: users_project.user.id
+ )
+ subject.after_create(users_project)
+ end
end
describe "#after_update" do
@@ -37,4 +45,23 @@ describe UsersProjectObserver do
subject.after_update(users_project)
end
end
+ describe "#after_destroy" do
+ it "should called when UsersProject destroyed" do
+ subject.should_receive(:after_destroy)
+ UsersProject.observers.enable :users_project_observer do
+ UsersProject.bulk_delete(
+ users_project.project,
+ [users_project.user.id]
+ )
+ end
+ end
+ it "should create new event" do
+ Event.should_receive(:create).with(
+ project_id: users_project.project.id,
+ action: Event::Left,
+ author_id: users_project.user.id
+ )
+ subject.after_destroy(users_project)
+ end
+ end
end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 23fb34e6e21..ec31ad2f25d 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -86,7 +86,7 @@ describe Gitlab::API do
it "should return a 404 error if not found" do
get api("/projects/42", user)
response.status.should == 404
- json_response['message'].should == '404 Not found'
+ json_response['message'].should == '404 Not Found'
end
end