diff --git a/.gitignore b/.gitignore
index ef7fd18e7..0511a9ffc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+*~
.bundle
.rvmrc
.DS_Store
diff --git a/Gemfile b/Gemfile
index 60869b4bb..891323817 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,6 @@
source 'http://rubygems.org'
-gem 'rails', '3.2.7' #, :git => 'git://github.com/rails/rails.git'
+gem 'rails', '3.2.8' #, :git => 'git://github.com/rails/rails.git'
gem 'pg', '~> 0.14.0'
# gem 'silent-postgres', :git => 'git://github.com/dolzenko/silent-postgres.git' #'~> 0.1.1'
@@ -25,14 +25,14 @@ gem 'state_machine'
# gem 'rugged', '~> 0.16.0'
gem 'grack', :git => 'git://github.com/rdblue/grack.git', :require => 'git_http'
gem "grit", :git => 'git://github.com/warpc/grit.git' #, :path => '~/Sites/code/grit'
-gem 'charlock_holmes', '~> 0.6.8' #, :git => 'git://github.com/brianmario/charlock_holmes.git', :branch => 'bundle-icu'
+gem 'charlock_holmes', '~> 0.6.9' #, :git => 'git://github.com/brianmario/charlock_holmes.git', :branch => 'bundle-icu'
# gem 'ruby-filemagic', '~> 0.4.2', :require => 'filemagic/ext'
-gem 'github-linguist', '~> 2.1.2', :require => 'linguist'
+gem 'github-linguist', '~> 2.2.1', :require => 'linguist'
gem 'diff-display', '~> 0.0.1'
# Wiki
-gem "gollum", :git => 'git://github.com/github/gollum.git'
-gem "redcarpet", "1.17.2"
+gem "gollum", '~> 2.1.3'
+gem "redcarpet", "~> 2.1.1"
gem 'creole'
gem 'rdiscount'
# gem 'org-ruby'
@@ -58,7 +58,7 @@ group :assets do
gem 'coffee-rails', '~> 3.2.2'
gem 'compass-rails', '~> 1.0.3'
gem 'uglifier', '~> 1.2.4'
- gem 'therubyracer', '~> 0.10.1', :platforms => [:mri, :rbx]
+ gem 'therubyracer', '~> 0.10.2', :platforms => [:mri, :rbx]
gem 'therubyrhino', '~> 1.73.1', :platforms => :jruby
end
@@ -81,7 +81,7 @@ end
group :test do
gem 'rspec-rails', '~> 2.11.0', :group => 'development'
- gem 'factory_girl_rails', '~> 3.6.0'
+ gem 'factory_girl_rails', '~> 4.0.0'
gem 'rr', '~> 1.0.4'
gem 'shoulda'
end
diff --git a/Gemfile.lock b/Gemfile.lock
index 896f7a8ab..b207f5084 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -6,23 +6,6 @@ GIT
redhillonrails_core (2.0.0.pre)
activerecord (>= 3.1.0.rc)
-GIT
- remote: git://github.com/github/gollum.git
- revision: 8422b712048656c8ea391c2d7ef27fb29f66746b
- specs:
- gollum (2.1.0)
- github-markdown
- github-markup (>= 0.7.0, < 1.0.0)
- grit (~> 2.5.0)
- mustache (>= 0.11.2, < 1.0.0)
- nokogiri (~> 1.4)
- posix-spawn (~> 0.3.0)
- pygments.rb (~> 0.2.0)
- sanitize (~> 2.0.0)
- sinatra (~> 1.0)
- stringex (~> 1.4.0)
- useragent (~> 0.4.9)
-
GIT
remote: git://github.com/rdblue/grack.git
revision: 020be3fef3fb308b9d214252522aa5945bf6584a
@@ -42,12 +25,12 @@ GEM
remote: http://rubygems.org/
specs:
RedCloth (4.2.9)
- actionmailer (3.2.7)
- actionpack (= 3.2.7)
+ actionmailer (3.2.8)
+ actionpack (= 3.2.8)
mail (~> 2.4.4)
- actionpack (3.2.7)
- activemodel (= 3.2.7)
- activesupport (= 3.2.7)
+ actionpack (3.2.8)
+ activemodel (= 3.2.8)
+ activesupport (= 3.2.8)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.4)
@@ -55,18 +38,18 @@ GEM
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.1.3)
- activemodel (3.2.7)
- activesupport (= 3.2.7)
+ activemodel (3.2.8)
+ activesupport (= 3.2.8)
builder (~> 3.0.0)
- activerecord (3.2.7)
- activemodel (= 3.2.7)
- activesupport (= 3.2.7)
+ activerecord (3.2.8)
+ activemodel (= 3.2.8)
+ activesupport (= 3.2.8)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
- activeresource (3.2.7)
- activemodel (= 3.2.7)
- activesupport (= 3.2.7)
- activesupport (3.2.7)
+ activeresource (3.2.8)
+ activemodel (= 3.2.8)
+ activesupport (= 3.2.8)
+ activesupport (3.2.8)
i18n (~> 0.6)
multi_json (~> 1.0)
airbrake (3.1.2)
@@ -92,9 +75,9 @@ GEM
net-ssh (>= 2.0.14)
net-ssh-gateway (>= 1.1.0)
capistrano_colors (0.5.5)
- charlock_holmes (0.6.8)
+ charlock_holmes (0.6.9)
chronic (0.6.7)
- chunky_png (1.2.5)
+ chunky_png (1.2.6)
cocaine (0.2.1)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
@@ -125,21 +108,33 @@ GEM
execjs (1.4.0)
multi_json (~> 1.0)
expression_parser (0.9.0)
- factory_girl (3.6.0)
+ factory_girl (4.0.0)
activesupport (>= 3.0.0)
- factory_girl_rails (3.6.0)
- factory_girl (~> 3.6.0)
+ factory_girl_rails (4.0.0)
+ factory_girl (~> 4.0.0)
railties (>= 3.0.0)
ffi (1.0.11)
fssm (0.2.9)
- github-linguist (2.1.2)
+ github-linguist (2.2.1)
charlock_holmes (~> 0.6.6)
escape_utils (~> 0.2.3)
mime-types (~> 1.18)
pygments.rb (>= 0.2.13)
github-markdown (0.5.0)
github-markup (0.7.4)
- haml (3.1.6)
+ gollum (2.1.3)
+ github-markdown
+ github-markup (>= 0.7.0, < 1.0.0)
+ grit (~> 2.5.0)
+ mustache (>= 0.11.2, < 1.0.0)
+ nokogiri (~> 1.4)
+ posix-spawn (~> 0.3.0)
+ pygments.rb (~> 0.2.0)
+ sanitize (~> 2.0.0)
+ sinatra (~> 1.0)
+ stringex (~> 1.4.0)
+ useragent (~> 0.4.9)
+ haml (3.1.7)
haml-rails (0.3.4)
actionpack (~> 3.0)
activesupport (~> 3.0)
@@ -150,7 +145,7 @@ GEM
hike (1.2.1)
hirb (0.7.0)
i18n (0.6.0)
- jbuilder (0.4.0)
+ jbuilder (0.4.3)
activesupport (>= 3.0.0)
blankslate (>= 2.1.2.4)
journey (1.0.4)
@@ -223,14 +218,14 @@ GEM
rack
rack-test (0.6.1)
rack (>= 1.0)
- rails (3.2.7)
- actionmailer (= 3.2.7)
- actionpack (= 3.2.7)
- activerecord (= 3.2.7)
- activeresource (= 3.2.7)
- activesupport (= 3.2.7)
+ rails (3.2.8)
+ actionmailer (= 3.2.8)
+ actionpack (= 3.2.8)
+ activerecord (= 3.2.8)
+ activeresource (= 3.2.8)
+ activesupport (= 3.2.8)
bundler (~> 1.0)
- railties (= 3.2.7)
+ railties (= 3.2.8)
rails-backbone (0.7.2)
coffee-script (~> 2.2.0)
ejs (~> 1.0.0)
@@ -239,9 +234,9 @@ GEM
railties (>= 3.0.0)
rails3-jquery-autocomplete (1.0.7)
rails (~> 3.0)
- railties (3.2.7)
- actionpack (= 3.2.7)
- activesupport (= 3.2.7)
+ railties (3.2.8)
+ actionpack (= 3.2.8)
+ activesupport (= 3.2.8)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
@@ -251,9 +246,9 @@ GEM
rdiscount (1.6.8)
rdoc (3.12)
json (~> 1.4)
- redcarpet (1.17.2)
+ redcarpet (2.1.1)
redis (3.0.1)
- redis-namespace (1.2.0)
+ redis-namespace (1.2.1)
redis (~> 3.0.0)
redisk (0.2.2)
redis (>= 0.1.1)
@@ -277,7 +272,7 @@ GEM
rspec-core (2.11.1)
rspec-expectations (2.11.2)
diff-lcs (~> 1.1.3)
- rspec-mocks (2.11.1)
+ rspec-mocks (2.11.2)
rspec-rails (2.11.0)
actionpack (>= 3.0)
activesupport (>= 3.0)
@@ -296,7 +291,7 @@ GEM
capistrano (>= 2.0.0)
sanitize (2.0.3)
nokogiri (>= 1.4.4, < 1.6)
- sass (3.1.20)
+ sass (3.2.0)
sass-rails (3.2.5)
railties (~> 3.2.0)
sass (>= 3.1.10)
@@ -324,19 +319,19 @@ GEM
state_machine (1.1.2)
stringex (1.4.0)
systemu (2.5.2)
- therubyracer (0.10.1)
+ therubyracer (0.10.2)
libv8 (~> 3.3.10)
thin (1.4.1)
daemons (>= 1.0.9)
eventmachine (>= 0.12.6)
rack (>= 1.0.0)
- thor (0.15.4)
+ thor (0.16.0)
tilt (1.3.3)
treetop (1.4.10)
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.33)
- uglifier (1.2.6)
+ uglifier (1.2.7)
execjs (>= 0.3.0)
multi_json (~> 1.3)
unicorn (4.3.1)
@@ -370,15 +365,15 @@ DEPENDENCIES
cape
capistrano
capistrano_colors
- charlock_holmes (~> 0.6.8)
+ charlock_holmes (~> 0.6.9)
coffee-rails (~> 3.2.2)
compass-rails (~> 1.0.3)
creole
devise (~> 2.1.2)
diff-display (~> 0.0.1)
- factory_girl_rails (~> 3.6.0)
- github-linguist (~> 2.1.2)
- gollum!
+ factory_girl_rails (~> 4.0.0)
+ github-linguist (~> 2.2.1)
+ gollum (~> 2.1.3)
grack!
grit!
haml-rails (~> 0.3.4)
@@ -394,12 +389,12 @@ DEPENDENCIES
paperclip (~> 3.1.4)
perform_later (~> 1.3.0)
pg (~> 0.14.0)
- rails (= 3.2.7)
+ rails (= 3.2.8)
rails-backbone (~> 0.7.2)
rails3-generators
rails3-jquery-autocomplete (~> 1.0.7)
rdiscount
- redcarpet (= 1.17.2)
+ redcarpet (~> 2.1.1)
redhillonrails_core!
resque (~> 1.21.0)
resque-status (~> 0.3.3)
@@ -413,7 +408,7 @@ DEPENDENCIES
shotgun
shoulda
state_machine
- therubyracer (~> 0.10.1)
+ therubyracer (~> 0.10.2)
therubyrhino (~> 1.73.1)
trinidad (~> 1.0.2)
uglifier (~> 1.2.4)
diff --git a/app/assets/images/trigger.gif b/app/assets/images/trigger.gif
new file mode 100644
index 000000000..4be7710be
Binary files /dev/null and b/app/assets/images/trigger.gif differ
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 6b311c6f5..69d7c1b0c 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -34,7 +34,7 @@ $(document).ready(function() {
var current = $(this);
current.parent().find('input.user_role_chbx').each(function(i,el) {
if ($(el).attr('id') != current.attr('id')) {
- $(el).removeAttr('checked');
+ $(el).removeAttr('checked');
}
});
});
@@ -81,4 +81,10 @@ $(document).ready(function() {
}
return false;
});
+
+ window.CodeMirrorRun = function(code) {
+ CodeMirror.runMode(code.innerHTML.replace(/&/gi, '&').replace(/</gi, '<').replace(/>/gi, '>'), code.className, code);
+ }
+
+ $('.md_and_cm code').each(function (code) { CodeMirrorRun(this); });
});
diff --git a/app/assets/javascripts/backbone/views/project_modify_view.js b/app/assets/javascripts/backbone/views/project_modify_view.js
new file mode 100644
index 000000000..348b9a50e
--- /dev/null
+++ b/app/assets/javascripts/backbone/views/project_modify_view.js
@@ -0,0 +1,23 @@
+Rosa.Views.ProjectModifyView = Backbone.View.extend({
+ initialize: function() {
+ _.bindAll(this, 'checkboxClick');
+
+ this.$checkbox_wrapper = $('#niceCheckbox1');
+ this._$checkbox = this.$checkbox_wrapper.children('#project_is_package').first();
+ this.$maintainer_form = $('#maintainer_form');
+
+ this.$checkbox_wrapper.on('click', this.checkboxClick);
+ },
+
+ checkboxClick: function() {
+ if (this._$checkbox.is(':checked')) {
+ this.$maintainer_form.slideDown();
+ } else {
+ this.$maintainer_form.slideUp();
+ }
+ },
+
+ render: function() {
+ this.checkboxClick();
+ }
+});
diff --git a/app/assets/javascripts/design/checkbox-main.js b/app/assets/javascripts/design/checkbox-main.js
index 225051b87..b8b219cfb 100644
--- a/app/assets/javascripts/design/checkbox-main.js
+++ b/app/assets/javascripts/design/checkbox-main.js
@@ -1,32 +1,32 @@
-function changeCheck(el) {
- var el = el, input = el.find('input[type="checkbox"]');
-
- if(input.attr("checked")) {
- el.css('backgroundPosition', '0 0');
- input.removeAttr('checked');
- } else {
- el.css('backgroundPosition', '0 -18px');
- input.attr('checked', true);
- }
-
- return true;
-}
-
-function startChangeCheck(el) {
- var el = el, input = el.find('input[type="checkbox"]');
-
- if(input.attr('checked')) {
- el.css('backgroundPosition', '0 -18px');
- }
-
- return true;
-}
-
-$(document).ready(function(){
- $('.niceCheck-main').each(function(i,el) {
- startChangeCheck($(el));
- });
- $('.niceCheck-main').click(function() {
- changeCheck($(this));
- });
-});
+function changeCheck(el) {
+ var input = el.find('input[type="checkbox"]');
+
+ if(input.attr("checked")) {
+ el.css('backgroundPosition', '0 0');
+ input.removeAttr('checked');
+ } else {
+ el.css('backgroundPosition', '0 -18px');
+ input.attr('checked', true);
+ }
+
+ return true;
+}
+
+function startChangeCheck(el) {
+ var input = el.find('input[type="checkbox"]');
+
+ if(input.attr('checked')) {
+ el.css('backgroundPosition', '0 -18px');
+ }
+
+ return true;
+}
+
+$(document).ready(function(){
+ $('.niceCheck-main').each(function(i,el) {
+ startChangeCheck($(el));
+ });
+ $('.niceCheck-main').click(function() {
+ changeCheck($(this));
+ });
+});
diff --git a/app/assets/javascripts/extra/build_list.js b/app/assets/javascripts/extra/build_list.js
index 6402c9e5d..99241e9cf 100644
--- a/app/assets/javascripts/extra/build_list.js
+++ b/app/assets/javascripts/extra/build_list.js
@@ -1,98 +1,47 @@
$(document).ready(function() {
// TODO: Refactor this handler!! It's too complicated.
- $('#build_list_save_to_platform_id').change(function() {
- var platform_id = $(this).val();
- var base_platforms = $('.all_platforms input[type=checkbox].build_bpl_ids');
+ $('#build_list_save_to_repository_id').change(function() {
+ var selected_option = $(this).find("option:selected");
- base_platforms.each(function(){
- if ($.inArray(platform_id, base_platforms.map(function(){ return $(this).val() }).get()) >= 0) {
- if ($(this).val() == platform_id) {
- if ($(this).attr('data-released') === '1') {
- $('#build_list_auto_publish').removeAttr('checked').attr('disabled', 'disabled');
- //disableUpdateTypes();
- } else {
- $('#build_list_auto_publish').removeAttr('disabled').attr('checked', 'checked');
- //enableUpdateTypes();
- }
+ var platform_id = selected_option.attr('platform_id');
+ var rep_name = selected_option.text().match(/[\w-]+\/([\w-]+)/)[1];
- $(this).attr('checked', 'checked').removeAttr('disabled').trigger('change');
- $(this).parent().find('.offset25 input[type="checkbox"]').removeAttr('disabled');
-
- var rep_name = $('#build_list_save_to_platform_id option[value="' + $(this).val() + '"]').text().match(/[\w-]+\/([\w-]+)/)[1];
- if (rep_name != 'main') {
- $(this).parent().find('.offset25 input[type="checkbox"][rep_name="' + rep_name + '"]').attr('checked', 'checked');
- }
- $(this).parent().find('.offset25 input[type="checkbox"][rep_name="main"]').attr('checked', 'checked');
- } else {
- $(this).removeAttr('checked').attr('disabled', 'disabled').trigger('change');
- $(this).parent().find('.offset25 input[type="checkbox"]').attr('disabled', 'disabled').removeAttr('checked');
- }
- } else {
- $(this).removeAttr('disabled').removeAttr('checked').trigger('change');
- $(this).parent().find('.offset25 input[type="checkbox"]').removeAttr('disabled').removeAttr('checked');
- $('#build_list_auto_publish').removeAttr('disabled').attr('checked', 'checked');
+ var build_platform = $('#build_for_pl_' + platform_id);
+ var all_repositories = $('.all_platforms input');
+ all_repositories.removeAttr('checked');
+ if (build_platform.size() == 0) {
+ all_repositories.removeAttr('disabled');
+ } else {
+ all_repositories.attr('disabled', 'disabled');
+ var parent = build_platform.parent();
+ parent.find('input').removeAttr('disabled');
+ parent.find('input[rep_name="main"]').attr('checked', 'checked');
+ if (rep_name != 'main') {
+ parent.find('input[rep_name="' + rep_name + '"]').attr('checked', 'checked');
}
- });
-
- if ($.inArray(platform_id, base_platforms.map(function(){ return $(this).val() }).get()) == -1) {
- // For personal platforms update types always enebaled:
- enableUpdateTypes();
+ setBranchSelected(selected_option);
+ }
+ var build_list_auto_publish = $('#build_list_auto_publish');
+ if (selected_option.attr('publish_without_qa') == '1') {
+ build_list_auto_publish.removeAttr('disabled').attr('checked', 'checked');
+ } else {
+ build_list_auto_publish.removeAttr('checked').attr('disabled', 'disabled');
}
-
-
- setBranchSelected();
- });
- $('#build_list_save_to_platform_id').trigger('change');
-
- $('.offset25 label').click(function() {
- setPlChecked($(this).prev()[0], !$(this).prev().attr('checked'));
- });
- $('.offset25 input[type="checkbox"]').click(function() {
- setPlChecked(this, $(this).attr('checked'));
- });
-
- $('.build_bpl_ids').click(function() {
- return false;
});
+ $('#build_list_save_to_repository_id').trigger('change');
});
-function setPlChecked(pointer, checked) {
- var pl_cbx = $(pointer).parent().parent().parent().find('input[type="checkbox"].build_bpl_ids');
- var pl_id = pl_cbx.val();
- if (checked && !$(pointer).attr('disabled')) {
- pl_cbx.attr('checked', 'checked').trigger('change');
- } else if ($('input[pl_id=' + pl_id + '][checked="checked"]').size() == 0) {
- pl_cbx.removeAttr('checked').trigger('change');
+function setBranchSelected(selected_option) {
+ var pl_name = selected_option.text().match(/([\w-.]+)\/[\w-.]+/)[1];
+ var bl_version_sel = $('#build_list_project_version');
+ var branch_pl_opt = bl_version_sel.find('option[value="latest_' + pl_name + '"]');
+ // If there is branch we need - set it selected:
+ if (branch_pl_opt.size() > 0) {
+ bl_version_sel.find('option[selected]').removeAttr('selected');
+ branch_pl_opt.attr('selected', 'selected');
+ bl_version_sel.val(branch_pl_opt);
+ // hack for FF to force render of select box.
+ bl_version_sel[0].innerHTML = bl_version_sel[0].innerHTML;
}
}
-
-function setBranchSelected() {
- var pl_id = $('#build_list_save_to_platform_id').val();
- // Checks if selected platform is main or not:
- if ( $('.all_platforms').find('input[type="checkbox"][value=' + pl_id + '].build_bpl_ids').size() > 0 ) {
- var pl_name = $('#build_list_save_to_platform_id option[value="' + pl_id + '"]').text().match(/([\w-.]+)\/[\w-.]+/)[1];
- var branch_pl_opt = $('#build_list_project_version option[value="latest_' + pl_name + '"]');
- // If there is branch we need - set it selected:
- if ( branch_pl_opt.size() > 0 ) {
- $('#build_list_project_version option[selected]').removeAttr('selected');
- branch_pl_opt.attr('selected', 'selected');
- }
- }
-}
-
-function disableUpdateTypes() {
- $("select#build_list_update_type option").each(function(i,el) {
- if ( $.inArray($(el).attr("value"), ["security", "bugfix"]) == -1 ) {
- $(el).attr("disabled", "disabled");
- // If disabled option is selected - select 'bugfix':
- if ( $(el).attr("selected") ) {
- $( $('select#build_list_update_type option[value="bugfix"]') ).attr("selected", "selected");
- }
- }
- });
-}
-
-function enableUpdateTypes() {
- $("select#build_list_update_type option").removeAttr("disabled");
-}
diff --git a/app/assets/javascripts/extra/comment.js b/app/assets/javascripts/extra/comment.js
new file mode 100644
index 000000000..5bcf3aa20
--- /dev/null
+++ b/app/assets/javascripts/extra/comment.js
@@ -0,0 +1,34 @@
+$(document).ready(function() {
+ $('.buttons a.edit_comment').live('click', function() {
+ $(this).parent().parent().parent().hide();
+ $('#open-comment'+'.comment.'+$(this).attr('id')).show();
+ return false;
+ });
+
+ $('.cancel_edit_comment.button').live('click', function() {
+ $(this).parent().parent().parent().hide();
+ $('.buttons a.edit_comment#'+$(this).attr('id')).parent().parent().parent().show();
+ return false;
+ });
+
+ $('form.edit_comment').live('submit', function() {
+ var form = $(this);
+ form.parent().find('.flash').remove();
+ $.ajax({
+ type: 'POST',
+ url: form.attr("action"),
+ data: form.serialize(),
+ success: function(data){
+ var cancel_button = form.find('.cancel_edit_comment.button');
+ cancel_button.click();
+ $('.buttons a.edit_comment#'+cancel_button.attr('id')).parent().parent().find('.cm-s-default.md_and_cm').html(data).find('code').each(function (code) { CodeMirrorRun(this); })
+ },
+ error: function(data){
+ form.before(data.responseText);
+ }
+ });
+ return false;
+ });
+
+
+});
diff --git a/app/assets/javascripts/extra/preview.js b/app/assets/javascripts/extra/preview.js
new file mode 100644
index 000000000..5f9002ea0
--- /dev/null
+++ b/app/assets/javascripts/extra/preview.js
@@ -0,0 +1,23 @@
+$(document).ready(function() {
+ var preview_url = $('#preview_url').val();
+ $('#md_tabs.nav.nav-tabs').each(function(i) { $(this).find('a:first').tab('show') });
+
+ $('#md_tabs a[data-toggle="tab"]').on('shown', function (e) {
+ if(e.relatedTarget) { var hash = e.relatedTarget.hash; }
+ else { var hash = e.currentTarget.hash; }
+ var el = $(hash+'_input');
+ var el_dup = $(hash+'_input_dup');
+ var preview = $(e.target.hash+' > .formatted.cm-s-default');
+ if(el.val() != el_dup.val() || preview.val() === '') {
+ el_dup.val(el.val());
+ $.ajax({
+ type: 'POST',
+ url: preview_url,
+ data: el_dup.serialize(),
+ success: function(data){
+ preview.html(data).find('code').each(function (code) { CodeMirrorRun(this); })
+ }
+ });
+ };
+ });
+});
diff --git a/app/assets/javascripts/extra/tracker.js b/app/assets/javascripts/extra/tracker.js
index 25dc641b6..24aaf3f2f 100644
--- a/app/assets/javascripts/extra/tracker.js
+++ b/app/assets/javascripts/extra/tracker.js
@@ -224,6 +224,7 @@ $(document).ready(function() {
$('.edit_form.issue').live('submit', function() {
var form = $(this);
+ form.parent().find('.flash').remove();
$.ajax({
type: 'POST',
url: form.attr("action"),
@@ -232,10 +233,10 @@ $(document).ready(function() {
form.fadeOut('slow');
$('#edit_issue_content').fadeIn('slow');
$('h3.issue_title').html(form.find('#issue_title').attr('value'));
- $('.fulltext.view.issue_body').html(form.find('#issue_body').attr('value'));
+ $('.fulltext.view.issue_body').html(data).find('code').each(function (code) { CodeMirrorRun(this); })
},
error: function(data){
- alert('error'); // TODO remove
+ form.before(data.responseText);
}
});
return false;
diff --git a/app/assets/stylesheets/design/custom.scss b/app/assets/stylesheets/design/custom.scss
index f374857d0..32d816e38 100644
--- a/app/assets/stylesheets/design/custom.scss
+++ b/app/assets/stylesheets/design/custom.scss
@@ -760,7 +760,7 @@ div.tos ol li {
}
div.tos_sidebar ul {
- list-style: none outside none;
+ list-style: none outside none;
margin: 20px 0 0;
padding: 0;
text-align: left;
@@ -1160,19 +1160,19 @@ form.mass_build section.right {
}
/* remove this lines after change to backbone */
-table.tablesorter.advisories thead tr.search th {
+table.tablesorter.static-search thead tr.search th {
padding: 0 5px;
}
-table.tablesorter.advisories thead tr.search th input[type='text'] {
+table.tablesorter.static-search thead tr.search th input[type='text'] {
width: 640px;
}
-table.tablesorter.advisories thead tr.search th form {
+table.tablesorter.static-search thead tr.search th form {
float: left;
}
-table.tablesorter.advisories thead tr.search th form.button_to {
+table.tablesorter.static-search thead tr.search th form.button_to {
padding: 3px 0 0 7px;
}
@@ -1401,10 +1401,238 @@ hr.bootstrap {
}
}
-time.js-relative-date {
- display: block;
-}
-
div.reloader {
float: right;
}
+
+div.log-wrapper {
+ width: 565px;
+
+ div.log-header {
+ margin-bottom: 10px;
+
+ div.text-wrap, span {
+ height: 16px;
+ margin: 0;
+ padding: 0;
+ }
+ div.text-wrap {
+ width: 545px;
+ float: left;
+
+ h3 {
+ margin: 0;
+ }
+ }
+
+ span {
+ background: image-url("trigger.gif") no-repeat scroll left bottom transparent;
+ margin: 1px;
+ cursor: pointer;
+ display: block;
+ font-size: 0;
+ height: 14px;
+ width: 14px;
+ float: right;
+ }
+ span.closed {
+ background-position: left top;
+ }
+ }
+
+ div.log-body {
+
+ div.reloader, .log {
+ border: 1px solid #ccc;
+ }
+
+ div.reloader {
+ padding: 5px 10px;
+ border-bottom: none;
+ border-radius: 5px 5px 0 0;
+
+ table.options {
+ border-spacing: 5px 0;
+
+ tr {
+
+ td a {
+ display: inline-block;
+ height: 13px;
+ padding-left: 16px;
+ background: image-url('code.png') no-repeat;
+ padding-bottom: 2px;
+ margin: 2px 0 0 1px;
+ }
+ td.first {
+ padding-right: 5px;
+ }
+ td.last {
+ border-left: 1px solid #ccc;
+ }
+ }
+
+ tr.bottom {
+ td {
+ padding-left: 5px;
+ }
+ td.first {
+ border-top: 1px solid #ccc;
+ }
+ }
+ }
+ }
+
+ .log {
+ background: #f8f8f8;
+ height: 500px;
+ width: 543px;
+ min-width: 543px;
+ border-radius: 5px 0 5px 5px;
+ overflow: auto;
+ padding: 10px;
+ margin: 0;
+ font-family: monospace;
+ font-size: 13px;
+ }
+ }
+}
+
+table.tablesorter.platform-maintainers.static-search thead tr.search th input[type="text"] {
+ width: 430px;
+}
+
+.all_platforms {
+ > .both { margin: 0 0 5px; }
+ .build_for_pl { font-weight: bold; }
+ .offset25 { padding-left: 10px }
+}
+
+.md_and_cm {
+ overflow: auto;
+ margin: 10px 0 10px;
+ padding: 5px;
+ border-radius: 4px 4px 4px 4px;
+ background: #FFF;
+
+ pre {
+ background-color: #F8F8F8;
+ border: 1px solid #D6D6D6;
+ border-radius: 5px 5px 5px 5px;
+ color: #333333;
+ padding: 6px 10px;
+ overflow: auto;
+
+ code {
+ background-color: transparent;
+ border: none;
+ }
+ }
+
+ code {
+ background-color: #F8F8F8;
+ border: 1px solid #D6D6D6;
+ border-radius: 5px 5px 5px 5px;
+ margin: 0 2px;
+ padding: 0px 5px;
+ }
+
+ blockquote {
+ border-left: 4px solid #EDEDED;
+ padding: 0 15px;
+ }
+
+ p {
+ margin-top: 10px;
+
+ }
+}
+
+.md_and_cm > :first-child {
+ margin-top: 0 !important;
+}
+
+#md_tabs {
+ margin: 0;
+}
+
+#md_tabs.nav-tabs > li > a {
+ line-height: 5px;
+}
+
+#open-comment {
+ textarea {
+ background: none repeat scroll 0 0 #FFFFFF;
+ border: 1px solid #DEDEDE;
+ border-radius: 4px 4px 4px 4px;
+ color: #575756;
+ font-size: 12px;
+ height: 110px;
+ padding: 5px;
+ width: 98%;
+ max-width: 98%;
+ margin: 10px 0 10px;
+ resize: vertical;
+ }
+
+ textarea#issue_title {
+ height: 16px;
+ margin: 0 0 10px;
+ }
+
+ .tab-pane textarea {
+ min-height: 112px;
+ }
+
+ .edit_comment .comment-left {
+ margin-top: 0;
+ }
+}
+
+#open-comment > h3.tmargin0 {
+ margin-bottom: 0;
+}
+
+#md_help {
+ width: 800px;
+ top: 30%;
+ left: 42%;
+
+ .modal-body {
+ max-height: 560px;
+ padding-top: 0;
+ }
+
+ .modal-header {
+ padding-bottom: 0;
+ }
+
+ .col {
+ width: 245px;
+ float: left;
+ padding: 0;
+ margin-right: 10px;
+
+ h3 {
+ margin: 6px 0 0 0;
+ }
+
+ pre {
+ background: none repeat scroll 0 0 #EDEDED;
+ box-shadow: 0 3px 3px -1px rgba(18, 86, 135, 0.2);
+ border: 1px solid #EDEDED;
+ padding: 5px;
+ margin-top: 3px;
+ }
+ }
+}
+
+#repo-wrapper .edit_form.issue div.comment div.wrapper {
+ background: 0;
+ border: 0;
+ border-radius: 0;
+ height: 30px;
+ margin: 0;
+ padding: 0;
+}
+
diff --git a/app/assets/stylesheets/design/main.scss b/app/assets/stylesheets/design/main.scss
index ba02e8d26..63a3fc533 100644
--- a/app/assets/stylesheets/design/main.scss
+++ b/app/assets/stylesheets/design/main.scss
@@ -828,11 +828,11 @@ article div.activity div.fulltext.view {
margin: 0px 0px 10px 0px;
}
-.right div.rightlist div.check {
+div.rightlist div.check {
float: left;
}
-.right div.rightlist div.forcheck {
+div.rightlist div.forcheck {
float: left;
margin: 1px 0px 0px 5px;
}
diff --git a/app/controllers/groups/profile_controller.rb b/app/controllers/groups/profile_controller.rb
index 1fd4ebab5..ff35cac4a 100644
--- a/app/controllers/groups/profile_controller.rb
+++ b/app/controllers/groups/profile_controller.rb
@@ -10,7 +10,7 @@ class Groups::ProfileController < Groups::BaseController
end
def show
- @projects = @group.projects #.paginate(:page => params[:project_page], :per_page => 10)
+ @projects = @group.projects.by_visibilities(['open'])
end
def new
diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb
index ebf5ed17c..2c8046360 100644
--- a/app/controllers/pages_controller.rb
+++ b/app/controllers/pages_controller.rb
@@ -9,11 +9,11 @@ class PagesController < ApplicationController
def tour_inside
@entries = case params[:id]
- when 'projects'
+ when 'builds'
%w(repo builds monitoring)
when 'sources'
%w(source history annotation edit)
- when 'builds'
+ when 'projects'
%w(control git tracker)
end
render "pages/tour/tour-inside", :layout => 'tour'
diff --git a/app/controllers/platforms/maintainers_controller.rb b/app/controllers/platforms/maintainers_controller.rb
new file mode 100644
index 000000000..386e48ae4
--- /dev/null
+++ b/app/controllers/platforms/maintainers_controller.rb
@@ -0,0 +1,15 @@
+# -*- encoding : utf-8 -*-
+class Platforms::MaintainersController < ApplicationController
+ before_filter :authenticate_user!
+ skip_before_filter :authenticate_user!, :only => [:index] if APP_CONFIG['anonymous_access']
+ load_and_authorize_resource :platform
+
+ def index
+ @maintainers = BuildList::Package.actual.by_platform(@platform)
+ .order('lower(name) ASC, length(name) ASC')
+ .includes(:project)
+ @maintainers = @maintainers.where('name ILIKE ?', "%#{params[:q]}%") if params[:q].present?
+ @maintainers = @maintainers.paginate(:page => params[:page])
+ end
+
+end
diff --git a/app/controllers/platforms/platforms_controller.rb b/app/controllers/platforms/platforms_controller.rb
index 5a948d06e..a35f64b5c 100644
--- a/app/controllers/platforms/platforms_controller.rb
+++ b/app/controllers/platforms/platforms_controller.rb
@@ -2,7 +2,7 @@
class Platforms::PlatformsController < Platforms::BaseController
before_filter :authenticate_user!
- skip_before_filter :authenticate_user!, :only => [:advisories] if APP_CONFIG['anonymous_access']
+ skip_before_filter :authenticate_user!, :only => [:advisories, :members, :show] if APP_CONFIG['anonymous_access']
load_and_authorize_resource
autocomplete :user, :uname
@@ -86,33 +86,23 @@ class Platforms::PlatformsController < Platforms::BaseController
end
def remove_members
- all_user_ids = params['user_remove'].inject([]) {|a, (k, v)| a << k if v.first == '1'; a}
- all_user_ids.each do |uid|
- Relation.by_target(@platform).where(:actor_id => uid, :actor_type => 'User').each{|r| r.destroy}
- end
+ user_ids = params[:user_remove] ?
+ params[:user_remove].map{ |k, v| k if v.first == '1' }.compact : []
+ User.where(:id => user_ids).each{ |user| @platform.remove_member(user) }
redirect_to members_platform_path(@platform)
end
def remove_member
- u = User.find(params[:member_id])
- Relation.by_actor(u).by_target(@platform).each{|r| r.destroy}
-
+ User.where(:id => params[:member_id]).each{ |user| @platform.remove_member(user) }
redirect_to members_platform_path(@platform)
end
def add_member
- if params[:member_id].present?
- member = User.find(params[:member_id])
- if @platform.relations.exists?(:actor_id => member.id, :actor_type => member.class.to_s) or @platform.owner == member
- flash[:warning] = t('flash.platform.members.already_added', :name => member.uname)
+ if member = User.where(:id => params[:member_id]).first
+ if @platform.add_member(member)
+ flash[:notice] = t('flash.platform.members.successfully_added', :name => member.uname)
else
- rel = @platform.relations.build(:role => 'admin')
- rel.actor = member
- if rel.save
- flash[:notice] = t('flash.platform.members.successfully_added', :name => member.uname)
- else
- flash[:error] = t('flash.platform.members.error_in_adding', :name => member.uname)
- end
+ flash[:error] = t('flash.platform.members.error_in_adding', :name => member.uname)
end
end
redirect_to members_platform_url(@platform)
diff --git a/app/controllers/platforms/product_build_lists_controller.rb b/app/controllers/platforms/product_build_lists_controller.rb
index bed67a54b..64bf45541 100644
--- a/app/controllers/platforms/product_build_lists_controller.rb
+++ b/app/controllers/platforms/product_build_lists_controller.rb
@@ -23,7 +23,7 @@ class Platforms::ProductBuildListsController < Platforms::BaseController
end
def destroy
- if @product_build_list.destroy
+ if @product_build_list.destroy
flash[:notice] = t('flash.product_build_list.delete')
else
flash[:error] = t('flash.product_build_list.delete_error')
diff --git a/app/controllers/platforms/products_controller.rb b/app/controllers/platforms/products_controller.rb
index 020866a1c..7d97915ba 100644
--- a/app/controllers/platforms/products_controller.rb
+++ b/app/controllers/platforms/products_controller.rb
@@ -1,7 +1,8 @@
# -*- encoding : utf-8 -*-
class Platforms::ProductsController < Platforms::BaseController
before_filter :authenticate_user!
-
+ skip_before_filter :authenticate_user!, :only => [:index, :show] if APP_CONFIG['anonymous_access']
+
load_and_authorize_resource :platform
load_and_authorize_resource :product, :through => :platform
diff --git a/app/controllers/platforms/repositories_controller.rb b/app/controllers/platforms/repositories_controller.rb
index 7e617e7d5..7afc34a21 100644
--- a/app/controllers/platforms/repositories_controller.rb
+++ b/app/controllers/platforms/repositories_controller.rb
@@ -1,9 +1,11 @@
# -*- encoding : utf-8 -*-
class Platforms::RepositoriesController < Platforms::BaseController
before_filter :authenticate_user!
+ skip_before_filter :authenticate_user!, :only => [:index, :show, :projects_list] if APP_CONFIG['anonymous_access']
load_and_authorize_resource :platform
load_and_authorize_resource :repository, :through => :platform, :shallow => true
+ before_filter :set_members, :only => [:edit, :update]
def index
@repositories = @repositories.paginate(:page => params[:page])
@@ -14,6 +16,46 @@ class Platforms::RepositoriesController < Platforms::BaseController
@projects = @projects.search(params[:query]).search_order if params[:query].present?
end
+ def edit
+ end
+
+ def update
+ if @repository.update_attributes(
+ :description => params[:repository][:description],
+ :publish_without_qa => (params[:repository][:publish_without_qa] || @repository.publish_without_qa)
+ )
+ flash[:notice] = I18n.t("flash.repository.updated")
+ redirect_to platform_repository_path(@platform, @repository)
+ else
+ flash[:error] = I18n.t("flash.repository.update_error")
+ flash[:warning] = @repository.errors.full_messages.join('. ')
+ render :action => :edit
+ end
+ end
+
+ def remove_members
+ user_ids = params[:user_remove] ?
+ params[:user_remove].map{ |k, v| k if v.first == '1' }.compact : []
+ User.where(:id => user_ids).each{ |user| @repository.remove_member(user) }
+ redirect_to edit_platform_repository_path(@platform, @repository)
+ end
+
+ def remove_member
+ User.where(:id => params[:member_id]).each{ |user| @repository.remove_member(user) }
+ redirect_to edit_platform_repository_path(@platform, @repository)
+ end
+
+ def add_member
+ if member = User.where(:id => params[:member_id]).first
+ if @repository.add_member(member)
+ flash[:notice] = t('flash.repository.members.successfully_added', :name => member.uname)
+ else
+ flash[:error] = t('flash.repository.members.error_in_adding', :name => member.uname)
+ end
+ end
+ redirect_to edit_platform_repository_path(@platform, @repository)
+ end
+
def new
@repository = Repository.new
@platform_id = params[:platform_id]
@@ -94,4 +136,10 @@ class Platforms::RepositoriesController < Platforms::BaseController
redirect_to platform_repository_path(@platform, @repository), :notice => t('flash.repository.project_removed')
end
+ protected
+
+ def set_members
+ @members = @repository.members.order('name')
+ end
+
end
diff --git a/app/controllers/projects/build_lists_controller.rb b/app/controllers/projects/build_lists_controller.rb
index 9045a49ed..742530992 100644
--- a/app/controllers/projects/build_lists_controller.rb
+++ b/app/controllers/projects/build_lists_controller.rb
@@ -5,9 +5,9 @@ class Projects::BuildListsController < Projects::BaseController
before_filter :authenticate_user!, :except => CALLBACK_ACTIONS
before_filter :authenticate_build_service!, :only => CALLBACK_ACTIONS
- skip_before_filter :authenticate_user!, :only => [:show, :index, :search] if APP_CONFIG['anonymous_access']
+ skip_before_filter :authenticate_user!, :only => [:show, :index, :search, :log] if APP_CONFIG['anonymous_access']
- before_filter :find_build_list, :only => [:show, :publish, :cancel, :update]
+ before_filter :find_build_list, :only => [:show, :publish, :cancel, :update, :log]
before_filter :find_build_list_by_bs, :only => [:publish_build, :status_build, :pre_build, :post_build, :circle_build]
load_and_authorize_resource :project, :only => NESTED_ACTIONS
@@ -44,15 +44,18 @@ class Projects::BuildListsController < Projects::BaseController
def create
notices, errors = [], []
- @platform = Platform.includes(:repositories).find params[:build_list][:save_to_platform_id]
+ @repository = Repository.find params[:build_list][:save_to_repository_id]
+ @platform = @repository.platform
- @repository = @project.repositories.where(:id => @platform.repository_ids).first
+ params[:build_list][:save_to_platform_id] = @platform.id
+ params[:build_list][:auto_publish] = false unless @repository.publish_without_qa?
- params[:build_list][:save_to_repository_id] = @repository.id
- params[:build_list][:auto_publish] = false if @platform.released
+
+ build_for_platforms = Repository.select(:platform_id).
+ where(:id => params[:build_list][:include_repos]).group(:platform_id).map(&:platform_id)
Arch.where(:id => params[:arches]).each do |arch|
- Platform.main.where(:id => params[:build_for_platforms]).each do |build_for_platform|
+ Platform.main.where(:id => build_for_platforms).each do |build_for_platform|
@build_list = @project.build_lists.build(params[:build_list])
@build_list.commit_hash = @project.repo.commits(@build_list.project_version.match(/^latest_(.+)/).to_a.last ||
@build_list.project_version).first.id if @build_list.project_version
@@ -101,6 +104,15 @@ class Projects::BuildListsController < Projects::BaseController
end
end
+ def log
+ @log = `tail -n #{params[:load_lines].to_i} #{Rails.root + 'public' + @build_list.fs_log_path}`
+ @log = t("layout.build_lists.log.not_available") unless $?.success?
+
+ respond_to do |format|
+ format.json { render :json => { :log => @log, :building => @build_list.build_started? } }
+ end
+ end
+
def publish_build
if params[:status].to_i == 0 # ok
@build_list.published
diff --git a/app/controllers/projects/comments_controller.rb b/app/controllers/projects/comments_controller.rb
index 3b36c3456..003ed166e 100644
--- a/app/controllers/projects/comments_controller.rb
+++ b/app/controllers/projects/comments_controller.rb
@@ -4,7 +4,7 @@ class Projects::CommentsController < Projects::BaseController
load_and_authorize_resource :project
before_filter :find_commentable
before_filter :find_or_build_comment
- load_and_authorize_resource
+ load_and_authorize_resource #:through => :commentable
include CommentsHelper
@@ -14,7 +14,8 @@ class Projects::CommentsController < Projects::BaseController
redirect_to project_commentable_path(@project, @commentable)
else
flash[:error] = I18n.t("flash.comment.save_error")
- render :action => 'new'
+ flash[:warning] = @comment.errors.full_messages.join('. ')
+ redirect_to project_commentable_path(@project, @commentable)
end
end
@@ -22,13 +23,12 @@ class Projects::CommentsController < Projects::BaseController
end
def update
- if @comment.update_attributes(params[:comment])
- flash[:notice] = I18n.t("flash.comment.saved")
- redirect_to project_commentable_path(@project, @commentable)
+ status, message = if @comment.update_attributes(params[:comment])
+ [200, view_context.markdown(@comment.body)]
else
- flash[:error] = I18n.t("flash.comment.save_error")
- render :action => 'new'
+ [400, view_context.local_alert(@comment.errors.full_messages.join('. '))]
end
+ render :inline => message, :status => status
end
def destroy
diff --git a/app/controllers/projects/git/trees_controller.rb b/app/controllers/projects/git/trees_controller.rb
index 45dae2aa1..d19e4fe31 100644
--- a/app/controllers/projects/git/trees_controller.rb
+++ b/app/controllers/projects/git/trees_controller.rb
@@ -1,6 +1,7 @@
# -*- encoding : utf-8 -*-
class Projects::Git::TreesController < Projects::Git::BaseController
- before_filter lambda{redirect_to @project if params[:treeish] == @project.default_branch and params[:path].blank?}, :only => 'show'
+ before_filter lambda{redirect_to @project if params[:treeish] == @project.default_branch and params[:path].blank?}, :only => :show
+ skip_before_filter :set_branch_and_tree, :only => :archive
def show
@tree = @tree / @path if @path.present?
@@ -9,13 +10,18 @@ class Projects::Git::TreesController < Projects::Git::BaseController
end
def archive
- @commit = @project.repo.log(@treeish, nil, :max_count => 1).first
+ format = params[:format]
+ if (@treeish =~ /^#{@project.owner.uname}-#{@project.name}-/) && !(@treeish =~ /[\s]+/) && (format =~ /^(zip|tar\.gz)$/)
+ @treeish = @treeish.gsub(/^#{@project.owner.uname}-#{@project.name}-/, '')
+ @commit = @project.repo.commits(@treeish, 1).first
+ end
raise Grit::NoSuchPathError unless @commit
- name = "#{@project.owner.uname}-#{@project.name}#{@project.repo.tags.include?(@treeish) ? "-#{@treeish}" : ''}-#{@commit.id[0..19]}"
- fullname = "#{name}.#{params[:format] == 'tar' ? 'tar.gz' : 'zip'}"
+ name = "#{@project.owner.uname}-#{@project.name}-#{@treeish}"
+ fullname = "#{name}.#{format == 'zip' ? 'zip' : 'tar.gz'}"
file = Tempfile.new fullname, 'tmp'
- system("cd #{@project.path}; git archive --format=#{params[:format]} --prefix=#{name}/ #{@treeish} #{params[:format] == 'tar' ? ' | gzip -9' : ''} > #{file.path}")
+ system("cd #{@project.path}; git archive --format=#{format} --prefix=#{name}/ #{@treeish} #{format == 'zip' ? '' : ' | gzip -9'} > #{file.path}")
file.close
- send_file file.path, :disposition => 'attachment', :type => "application/#{params[:format] == 'tar' ? 'x-tar-gz' : 'zip'}", :filename => fullname
+ send_file file.path, :disposition => 'attachment', :type => "application/#{format == 'zip' ? 'zip' : 'x-tar-gz'}", :filename => fullname
end
+
end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index bc1d28d77..dbf9e5841 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -1,33 +1,31 @@
# -*- encoding : utf-8 -*-
class Projects::IssuesController < Projects::BaseController
- NON_RESTFUL_ACTION = [:create_label, :update_label, :destroy_label, :search_collaborators]
+ NON_RESTFUL_ACTION = [:create_label, :update_label, :destroy_label]
before_filter :authenticate_user!
skip_before_filter :authenticate_user!, :only => [:index, :show] if APP_CONFIG['anonymous_access']
load_resource :project
load_and_authorize_resource :issue, :through => :project, :find_by => :serial_id, :only => [:show, :edit, :update, :destroy, :new, :create, :index]
before_filter :load_and_authorize_label, :only => NON_RESTFUL_ACTION
- layout 'application'
+ layout false, :only => [:update, :search_collaborators]
def index(status = 200)
@labels = params[:labels] || []
@issues = @project.issues.includes(:pull_request).includes(:assignee, :user)
@issues = @issues.where(:assignee_id => current_user.id) if @is_assigned_to_me = params[:filter] == 'to_me'
@issues = @issues.joins(:labels).where(:labels => {:name => @labels}) unless @labels == []
-
+ # Using mb_chars for correct transform to lowercase ('Русский Текст'.downcase => "Русский Текст")
@issues = @issues.where('issues.title ILIKE ?', "%#{params[:search_issue].mb_chars.downcase}%") if params[:search_issue]
- @opened_issues = @issues.not_closed_or_merged.count
- @closed_issues = @issues.closed_or_merged.count
- @issues = @issues
+
+ @opened_issues, @closed_issues = @issues.not_closed_or_merged.count, @issues.closed_or_merged.count
if params[:status] == 'closed'
- @issues = @issues.closed_or_merged
- @status = params[:status]
+ @issues, @status = @issues.closed_or_merged, params[:status]
else
- @issues = @issues.not_closed_or_merged
- @status = 'open'
+ @issues, @status = @issues.not_closed_or_merged, 'open'
end
- @issues = @issues.order('issues.serial_id desc').uniq.paginate :per_page => 10, :page => params[:page]
+ @issues = @issues.includes(:assignee, :user).order('issues.serial_id desc').uniq
+ .paginate :per_page => 10, :page => params[:page]
if status == 200
render 'index', :layout => request.xhr? ? 'issues' : 'application'
else
@@ -36,17 +34,14 @@ class Projects::IssuesController < Projects::BaseController
end
def new
- @issue = @project.issues.new
end
def create
@assignee_uname = params[:assignee_uname]
- @issue = @project.issues.new(params[:issue])
@issue.user_id = current_user.id
if @issue.save
@issue.subscribe_creator(current_user.id)
-
flash[:notice] = I18n.t("flash.issue.saved")
redirect_to project_issues_path(@project)
else
@@ -60,41 +55,39 @@ class Projects::IssuesController < Projects::BaseController
end
def update
+ @issue.labelings.destroy_all if params[:update_labels]
if params[:issue] && status = params[:issue][:status]
- action = 'status'
@issue.set_close(current_user) if status == 'closed'
@issue.set_open if status == 'open'
- status = 200 if @issue.save
- render :partial => action, :status => (status || 500), :layout => false
+ render :partial => 'status', :status => (@issue.save ? 200 : 400)
elsif params[:issue]
- @issue.labelings.destroy_all if params[:issue][:labelings_attributes] # FIXME
- status = 200 if @issue.update_attributes(params[:issue])
- render :nothing => true, :status => (status || 500), :layout => false
+ status, message = if @issue.update_attributes(params[:issue])
+ [200, view_context.markdown(@issue.body)]
+ else
+ [400, view_context.local_alert(@issue.errors.full_messages.join('. '))]
+ end
+ render :inline => message, :status => status
else
- render :nothing => true, :status => 200, :layout => false
+ render :nothing => true, :status => 200
end
end
def destroy
@issue.destroy
-
flash[:notice] = t("flash.issue.destroyed")
redirect_to root_path
end
def create_label
- status = @project.labels.create!(:name => params[:name], :color => params[:color]) ? 200 : 500
- index(status)
+ index(@project.labels.create!(:name => params[:name], :color => params[:color]) ? 200 : 500)
end
def update_label
- status = @label.update_attributes(:name => params[:name], :color => params[:color]) ? 200 : 500
- index(status)
+ index(@label.update_attributes(:name => params[:name], :color => params[:color]) ? 200 : 500)
end
def destroy_label
- status = (@label && @label_destroy) ? 200 : 500
- index(status)
+ index((@label && @label_destroy) ? 200 : 500)
end
def search_collaborators
@@ -102,7 +95,7 @@ class Projects::IssuesController < Projects::BaseController
users = User.joins(:groups => :projects).where(:projects => {:id => @project.id}).where("users.uname ILIKE ?", search)
users2 = @project.collaborators.where("users.uname ILIKE ?", search)
@users = (users + users2).uniq.sort {|x,y| x.uname <=> y.uname}.first(10)
- render :partial => 'search_collaborators', :layout => false
+ render :partial => 'search_collaborators'
end
private
diff --git a/app/controllers/projects/projects_controller.rb b/app/controllers/projects/projects_controller.rb
index 30b452dc4..b3f0906e2 100644
--- a/app/controllers/projects/projects_controller.rb
+++ b/app/controllers/projects/projects_controller.rb
@@ -5,9 +5,7 @@ class Projects::ProjectsController < Projects::BaseController
def index
@projects = Project.accessible_by(current_ability, :membered)
- # @projects = @projects.search(params[:query]).search_order if params[:query].present?
- #puts prepare_list(@projects).inspect
respond_to do |format|
format.html { @projects = @projects.recent.paginate(:page => params[:page], :per_page => 25) }
format.json { @projects = prepare_list(@projects) }
@@ -39,6 +37,7 @@ class Projects::ProjectsController < Projects::BaseController
end
def update
+ params[:project].delete(:maintainer_id) if params[:project][:maintainer_id].blank?
if @project.update_attributes(params[:project])
flash[:notice] = t('flash.project.saved')
redirect_to @project
@@ -86,6 +85,18 @@ class Projects::ProjectsController < Projects::BaseController
redirect_to projects_path
end
+ def autocomplete_maintainers
+ term, limit = params[:term], params[:limit] || 10
+ items = User.member_of_project(@project)
+ .where("users.name ILIKE ? OR users.uname ILIKE ?", "%#{term}%", "%#{term}%")
+ .limit(limit).map { |u| {:value => u.fullname, :label => u.fullname, :id => u.id} }
+ render :json => items
+ end
+
+ def preview
+ render :inline => view_context.markdown(params[:text]), :layout => false
+ end
+
protected
def prepare_list(projects)
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index bea77c80a..f4bf67e81 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -5,7 +5,6 @@ class SearchController < ApplicationController
def index
params[:type] ||= 'all'
- params[:type] = 'projects' unless current_user
case params[:type]
when 'all'
find_collection('projects')
diff --git a/app/controllers/users/profile_controller.rb b/app/controllers/users/profile_controller.rb
index 1e7c18869..25aa15e31 100644
--- a/app/controllers/users/profile_controller.rb
+++ b/app/controllers/users/profile_controller.rb
@@ -3,8 +3,6 @@ class Users::ProfileController < Users::BaseController
autocomplete :user, :uname
def show
- @groups = @user.groups.uniq
- @platforms = @user.platforms.paginate(:page => params[:platform_page], :per_page => 10)
- @projects = @user.projects.paginate(:page => params[:project_page], :per_page => 10)
+ @projects = @user.projects.by_visibilities(['open'])
end
end
diff --git a/app/controllers/users/register_requests_controller.rb b/app/controllers/users/register_requests_controller.rb
index 234ef39ab..a21249cdb 100644
--- a/app/controllers/users/register_requests_controller.rb
+++ b/app/controllers/users/register_requests_controller.rb
@@ -8,6 +8,7 @@ class Users::RegisterRequestsController < ApplicationController
end
def create
+ params[:register_request][:language] = I18n.locale if params[:register_request]
RegisterRequest.create(params[:register_request])
render :thanks
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 26ed84332..970715327 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -39,4 +39,19 @@ module ApplicationHelper
else object.class.name
end
end
+
+ def markdown(text)
+ unless @redcarpet
+ html_options = {filter_html: true, hard_wrap: true, with_toc_data: true}
+ options = {no_intraemphasis: true, tables: true, fenced_code_blocks: true, autolink: true, strikethrough: true, lax_html_blocks: true}
+ @redcarpet = Redcarpet::Markdown.new(Redcarpet::Render::HTML.new(html_options), options)
+ end
+ @redcarpet.render(text).html_safe
+ end
+
+ def local_alert(text, type = 'error')
+ html = "
#{text}"
+ html << link_to('×', '#', :class => 'close close-alert', 'data-dismiss' => 'alert')
+ html << '
'
+ end
end
diff --git a/app/helpers/build_lists_helper.rb b/app/helpers/build_lists_helper.rb
index 6509b3cb5..367ba78e7 100644
--- a/app/helpers/build_lists_helper.rb
+++ b/app/helpers/build_lists_helper.rb
@@ -43,4 +43,22 @@ module BuildListsHelper
build_list.project_version
end
end
+
+ def container_url
+ "http://#{request.host_with_port}/downloads#{@build_list.container_path}".html_safe
+ end
+
+ def build_list_log_url(log_type)
+ "http://#{request.host_with_port}/#{@build_list.fs_log_path(log_type)}".html_safe
+ end
+
+ def log_reload_time_options
+ t = I18n.t("layout.build_lists.log.reload_times").map { |i| i.reverse }
+
+ options_for_select(t, t.first).html_safe
+ end
+
+ def log_reload_lines_options
+ options_for_select([100, 200, 500, 1000, 1500, 2000], 1000).html_safe
+ end
end
diff --git a/app/mailers/feedback_mailer.rb b/app/mailers/feedback_mailer.rb
index 1d38f4e4d..272849100 100644
--- a/app/mailers/feedback_mailer.rb
+++ b/app/mailers/feedback_mailer.rb
@@ -4,6 +4,7 @@ class FeedbackMailer < ActionMailer::Base
default :to => FBM_CONFIG['email'],
:cc => FBM_CONFIG['cc'],
:bcc => FBM_CONFIG['bcc']
+ default_url_options.merge!(:protocol => 'https') if APP_CONFIG['mailer_https_url']
include Resque::Mailer # send email async
diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb
index e19cb799f..057c735cc 100644
--- a/app/mailers/user_mailer.rb
+++ b/app/mailers/user_mailer.rb
@@ -2,6 +2,7 @@
class UserMailer < ActionMailer::Base
default :from => APP_CONFIG['do-not-reply-email']
+ default_url_options.merge!(:protocol => 'https') if APP_CONFIG['mailer_https_url']
include Resque::Mailer # send email async
@@ -36,8 +37,24 @@ class UserMailer < ActionMailer::Base
end
end
+ def build_list_notification(build_list, user)
+ I18n.locale = user.language if user.language
+ @user, @build_list = user, build_list
+
+ subject = "[№ #{build_list.bs_id.present? ? build_list.bs_id : t("layout.build_lists.bs_id_not_set")}] "
+ subject << (build_list.project ? build_list.project.name_with_owner : t("layout.projects.unexisted_project"))
+ subject << " - #{build_list.human_status} "
+ subject << I18n.t("notifications.subjects.for_arch", :arch => @build_list.arch.name)
+ mail(:to => user.email, :subject => subject) do |format|
+ format.html
+ end
+ end
+
def invite_approve_notification(register_request)
+ I18n.locale = register_request.language if register_request.language
@register_request = register_request
- mail :to => register_request.email, :subject => I18n.t("notifications.subjects.invite_approve_notification")
+ mail :to => register_request.email, :subject => I18n.t("notifications.subjects.invite_approve_notification") do |format|
+ format.html
+ end
end
end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index ad2c9205c..bbeff275b 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -13,18 +13,22 @@ class Ability
@user = user
# Shared rights between guests and registered users
- can :show, Project, :visibility => 'open'
- can :archive, Project, :visibility => 'open'
+ can [:show, :archive], Project, :visibility => 'open'
can :read, Issue, :project => {:visibility => 'open'}
can :read, PullRequest, :project => {:visibility => 'open'}
can :search, BuildList
- can [:read, :everything], BuildList, :project => {:visibility => 'open'}
+ can [:read, :log, :everything], BuildList, :project => {:visibility => 'open'}
can :read, ProductBuildList#, :product => {:platform => {:visibility => 'open'}} # double nested hash don't work
can :read, Advisory
- can(:advisories, Platform) {APP_CONFIG['anonymous_access']}
+
# Core callbacks
can [:publish_build, :status_build, :pre_build, :post_build, :circle_build, :new_bbdt], BuildList
+ # Platforms block
+ can [:show, :members, :advisories], Platform, :visibility == 'open'
+ can [:read, :projects_list], Repository, :platform => {:visibility => 'open'}
+ can :read, Product, :platform => {:visibility => 'open'}
+
if user.guest? # Guest rights
# can [:new, :create], RegisterRequest
else # Registered user rights
@@ -56,52 +60,49 @@ class Ability
can [:read, :archive], Project, :owner_type => 'Group', :owner_id => user.group_ids
can([:read, :membered], Project, read_relations_for('projects')) {|project| local_reader? project}
can(:write, Project) {|project| local_writer? project} # for grack
- can([:update, :sections, :manage_collaborators], Project) {|project| local_admin? project}
+ can([:update, :sections, :manage_collaborators, :autocomplete_maintainers], Project) {|project| local_admin? project}
can(:fork, Project) {|project| can? :read, project}
can(:fork, Project) {|project| project.owner_type == 'Group' and can? :update, project.owner}
can(:destroy, Project) {|project| owner? project}
can(:destroy, Project) {|project| project.owner_type == 'Group' and project.owner.actors.exists?(:actor_type => 'User', :actor_id => user.id, :role => 'admin')}
can :remove_user, Project
- can [:autocomplete_base_project_name, :autocomplete_head_project_name], Project
+ can [:preview, :autocomplete_base_project_name, :autocomplete_head_project_name], Project
- can [:read, :owned, :everything], BuildList, :user_id => user.id
- can [:read, :related, :everything], BuildList, :project => {:owner_type => 'User', :owner_id => user.id}
- can [:read, :related, :everything], BuildList, :project => {:owner_type => 'Group', :owner_id => user.group_ids}
- can([:read, :everything], BuildList, read_relations_for('build_lists', 'projects')) {|build_list| can? :read, build_list.project}
+ can [:read, :log, :owned, :everything], BuildList, :user_id => user.id
+ can [:read, :log, :related, :everything], BuildList, :project => {:owner_type => 'User', :owner_id => user.id}
+ can [:read, :log, :related, :everything], BuildList, :project => {:owner_type => 'Group', :owner_id => user.group_ids}
+ can([:read, :log, :everything], BuildList, read_relations_for('build_lists', 'projects')) {|build_list| can? :read, build_list.project}
can([:create, :update], BuildList) {|build_list| build_list.project.is_package && can?(:write, build_list.project)}
can(:publish, BuildList) do |build_list|
- build_list.can_publish? and build_list.save_to_platform.released ? local_admin?(build_list.save_to_platform) : can?(:write, build_list.project)
+ build_list.can_publish? and build_list.save_to_repository.publish_without_qa ? can?(:write, build_list.project) : local_admin?(build_list.save_to_platform)
end
can(:reject_publish, BuildList) do |build_list|
- build_list.can_reject_publish? and build_list.save_to_platform.released and local_admin?(build_list.save_to_platform)
+ build_list.can_reject_publish? and not build_list.save_to_repository.publish_without_qa and local_admin?(build_list.save_to_platform)
end
can(:cancel, BuildList) {|build_list| build_list.can_cancel? && can?(:write, build_list.project)}
- can [:read], Advisory
-
- can [:read, :members], Platform, :visibility => 'open'
can [:read, :owned, :related, :members], Platform, :owner_type => 'User', :owner_id => user.id
can [:read, :related, :members], Platform, :owner_type => 'Group', :owner_id => user.group_ids
can([:read, :related, :members], Platform, read_relations_for('platforms')) {|platform| local_reader? platform}
can([:update, :members], Platform) {|platform| local_admin? platform}
can([:destroy, :members, :add_member, :remove_member, :remove_members] , Platform) {|platform| owner?(platform) || local_admin?(platform) }
- can [:autocomplete_user_uname, :read_advisories, :advisories], Platform
+ can [:autocomplete_user_uname], Platform
can([:failed_builds_list, :create], MassBuild) {|mass_build| (owner?(mass_build.platform) || local_admin?(mass_build.platform)) && mass_build.platform.main? }
can(:cancel, MassBuild) {|mass_build| (owner?(mass_build.platform) || local_admin?(mass_build.platform)) && !mass_build.stop_build && mass_build.platform.main?}
- can [:read, :projects_list], Repository, :platform => {:visibility => 'open'}
can [:read, :projects_list], Repository, :platform => {:owner_type => 'User', :owner_id => user.id}
can [:read, :projects_list], Repository, :platform => {:owner_type => 'Group', :owner_id => user.group_ids}
can([:read, :projects_list], Repository, read_relations_for('repositories', 'platforms')) {|repository| local_reader? repository.platform}
- can([:create, :update, :projects_list, :add_project, :remove_project], Repository) {|repository| local_admin? repository.platform}
+ can([:create, :edit, :update, :destroy, :projects_list, :add_project, :remove_project], Repository) {|repository| local_admin? repository.platform}
+ can([:remove_members, :remove_member, :add_member], Repository) {|repository| owner?(repository.platform) || local_admin?(repository.platform)}
+ can([:add_project, :remove_project], Repository) {|repository| repository.members.exists?(:id => user.id)}
can(:clear, Platform) {|platform| local_admin?(platform) && platform.personal?}
- can([:change_visibility, :settings, :destroy], Repository) {|repository| owner? repository.platform}
+ can([:change_visibility, :settings, :destroy, :edit, :update], Repository) {|repository| owner? repository.platform}
can([:create, :destroy], KeyPair) {|key_pair| owner?(key_pair.repository.platform) || local_admin?(key_pair.repository.platform)}
- can :read, Product, :platform => {:visibility => 'open'}
can :read, Product, :platform => {:owner_type => 'User', :owner_id => user.id, :platform_type => 'main'}
can :read, Product, :platform => {:owner_type => 'Group', :owner_id => user.group_ids, :platform_type => 'main'}
can(:read, Product, read_relations_for('products', 'platforms')) {|product| product.platform.main?}
@@ -116,20 +117,21 @@ class Ability
can :read, Issue, :project => {:owner_type => 'User', :owner_id => user.id}
can :read, Issue, :project => {:owner_type => 'Group', :owner_id => user.group_ids}
can(:read, Issue, read_relations_for('issues', 'projects')) {|issue| can? :read, issue.project rescue nil}
- can([:merge, :create], Issue) {|issue| can? :write, issue.project}
+ can(:merge, Issue) {|issue| can? :write, issue.project}
+ can(:create, Issue) {|issue| can? :read, issue.project}
can([:update, :destroy], Issue) {|issue| issue.user_id == user.id or local_admin?(issue.project)}
cannot :manage, Issue, :project => {:has_issues => false} # switch off issues
can(:autocomplete_base_project, Issue, read_relations_for('issues', 'projects')) {|issue| can? :read, issue.project rescue nil}
can(:create, Comment) {|comment| can? :read, comment.project}
- can(:update, Comment) {|comment| comment.user_id == user.id or local_admin?(comment.project || comment.commentable.project)}
+ can(:update, Comment) {|comment| comment.user == user or comment.project.owner == user or local_admin?(comment.project)}
cannot :manage, Comment, :commentable_type => 'Issue', :commentable => {:project => {:has_issues => false}} # switch off issues
end
# Shared cannot rights for all users (registered, admin)
cannot :destroy, Platform, :platform_type => 'personal'
- cannot [:create, :destroy, :add_project, :remove_project], Repository, :platform => {:platform_type => 'personal'}
+ cannot [:create, :destroy, :edit, :update, :add_project, :remove_project], Repository, :platform => {:platform_type => 'personal'}
cannot :clear, Platform, :platform_type => 'main'
cannot :destroy, Issue
diff --git a/app/models/build_list.rb b/app/models/build_list.rb
index 07cc933b8..2f540422c 100644
--- a/app/models/build_list.rb
+++ b/app/models/build_list.rb
@@ -79,7 +79,7 @@ class BuildList < ActiveRecord::Base
scope :recent, order("#{table_name}.updated_at DESC")
scope :for_status, lambda {|status| where(:status => status) }
scope :for_user, lambda { |user| where(:user_id => user.id) }
- scope :for_platform, lambda { |platform| where(:build_for_platform_id => platform.id) }
+ scope :for_platform, lambda { |platform| where(:build_for_platform_id => platform) }
scope :by_mass_build, lambda { |mass_build| where(:mass_build_id => mass_build) }
scope :scoped_to_arch, lambda {|arch| where(:arch_id => arch) }
scope :scoped_to_save_platform, lambda {|pl_id| where(:save_to_platform_id => pl_id) }
@@ -125,7 +125,11 @@ class BuildList < ActiveRecord::Base
end
end
- after_transition :on => :published, :do => :set_version_and_tag
+ after_transition :on => :published, :do => [:set_version_and_tag, :actualize_packages]
+
+ after_transition :on => [:published, :fail_publish, :build_error], :do => :notify_users
+ after_transition :on => :build_success, :do => :notify_users,
+ :unless => lambda { |build_list| build_list.auto_publish? }
event :place_build do
transition :waiting_for_response => :build_pending, :if => lambda { |build_list|
@@ -201,6 +205,19 @@ class BuildList < ActiveRecord::Base
save
end
+ def actualize_packages
+ ActiveRecord::Base.transaction do
+ old_pkgs = self.class.where(:project_id => self.project_id)
+ .where(:save_to_repository_id => self.save_to_repository_id)
+ .for_platform(self.build_for_platform_id)
+ .scoped_to_arch(self.arch_id)
+ .for_status(BUILD_PUBLISHED)
+ .recent.limit(2).last.packages # packages from previous build_list
+ old_pkgs.update_all(:actual => false)
+ self.packages.update_all(:actual => true)
+ end
+ end
+
#TODO: Share this checking on product owner.
def can_cancel?
[BUILD_PENDING, BuildServer::PLATFORM_PENDING].include?(status) && bs_id
@@ -211,7 +228,7 @@ class BuildList < ActiveRecord::Base
end
def can_reject_publish?
- can_publish? and save_to_platform.released
+ can_publish? and not save_to_repository.publish_without_qa
end
@@ -266,6 +283,10 @@ class BuildList < ActiveRecord::Base
I18n.t("layout.build_lists.human_duration", {:hours => (duration/3600).to_i, :minutes => (duration%3600/60).to_i})
end
+ def fs_log_path(log_type = :build)
+ container_path? ? "downloads/#{container_path}/log/#{project.name}/#{log_type.to_s}.log" : nil
+ end
+
def in_work?
status == BuildServer::BUILD_STARTED
#[WAITING_FOR_RESPONSE, BuildServer::BUILD_PENDING, BuildServer::BUILD_STARTED].include?(status)
@@ -273,6 +294,22 @@ class BuildList < ActiveRecord::Base
protected
+ def notify_users
+ unless mass_build_id
+ users = []
+ if project # find associated users
+ users = project.all_members.
+ select{ |user| user.notifier.can_notify? && user.notifier.new_associated_build? }
+ end
+ if user.notifier.can_notify? && user.notifier.new_build?
+ users = users | [user]
+ end
+ users.each do |user|
+ UserMailer.build_list_notification(self, user).deliver
+ end
+ end
+ end # notify_users
+
def delete_container
if can_cancel?
BuildServer.delete_build_list bs_id
diff --git a/app/models/build_list/package.rb b/app/models/build_list/package.rb
index b491c0d13..ce894412b 100644
--- a/app/models/build_list/package.rb
+++ b/app/models/build_list/package.rb
@@ -7,6 +7,18 @@ class BuildList::Package < ActiveRecord::Base
attr_accessible :fullname, :name, :release, :version
- validates :build_list_id, :project_id, :platform_id, :fullname, :package_type, :name, :release, :version, :presence => true
+ validates :build_list_id, :project_id, :platform_id, :fullname,
+ :package_type, :name, :release, :version,
+ :presence => true
validates :package_type, :inclusion => PACKAGE_TYPES
+
+ # Fetches only actual (last publised) packages.
+ scope :actual, where(:actual => true)
+ scope :by_platform, lambda {|platform| where(:platform_id => platform) }
+ scope :by_name, lambda {|name| where(:name => name) }
+ scope :by_package_type, lambda {|type| where(:package_type => type) }
+
+ def assignee
+ project.maintainer
+ end
end
diff --git a/app/models/build_list_observer.rb b/app/models/build_list_observer.rb
index bc54e088d..2d12b85d0 100644
--- a/app/models/build_list_observer.rb
+++ b/app/models/build_list_observer.rb
@@ -16,5 +16,6 @@ class BuildListObserver < ActiveRecord::Observer
end
end
end
- end
+ end # before_update
+
end
diff --git a/app/models/mass_build.rb b/app/models/mass_build.rb
index 4fa18720e..8383151f7 100644
--- a/app/models/mass_build.rb
+++ b/app/models/mass_build.rb
@@ -45,8 +45,8 @@ class MassBuild < ActiveRecord::Base
end
def cancel_all
- self.update_attribute(:stop_build, true)
- self.build_lists.find_each(:batch_size => 100) do |bl|
+ update_column(:stop_build, true)
+ build_lists.find_each(:batch_size => 100) do |bl|
bl.cancel
end
end
diff --git a/app/models/platform.rb b/app/models/platform.rb
index c0b13246a..49a84e898 100644
--- a/app/models/platform.rb
+++ b/app/models/platform.rb
@@ -28,13 +28,12 @@ class Platform < ActiveRecord::Base
before_create :xml_rpc_create, :unless => lambda {Thread.current[:skip]}
before_destroy :xml_rpc_destroy
- after_update :freeze_platform
+ after_update :freeze_platform_and_update_repos
+ after_update :update_owner_relation
after_create lambda { symlink_directory unless hidden? }
after_destroy lambda { remove_symlink_directory unless hidden? }
- after_update :update_owner_relation
-
scope :search_order, order("CHAR_LENGTH(name) ASC")
scope :search, lambda {|q| where("name ILIKE ?", "%#{q.to_s.strip}%")}
scope :by_visibilities, lambda {|v| where(:visibility => v)}
@@ -74,6 +73,14 @@ class Platform < ActiveRecord::Base
build_path(name)
end
+ def add_member(member, role = 'admin')
+ Relation.add_member(member, self, role)
+ end
+
+ def remove_member(member)
+ Relation.remove_member(member, self)
+ end
+
def symlink_path
Rails.root.join("public", "downloads", name)
end
@@ -131,11 +138,11 @@ class Platform < ActiveRecord::Base
end
def change_visibility
- if !self.hidden?
- self.update_attribute(:visibility, 'hidden')
+ if !hidden?
+ update_attributes(:visibility => 'hidden')
remove_symlink_directory
else
- self.update_attribute(:visibility, 'open')
+ update_attributes(:visibility => 'open')
symlink_directory
end
end
@@ -230,10 +237,11 @@ class Platform < ActiveRecord::Base
end
later :xml_rpc_clone, :loner => true, :queue => :clone_build
- def freeze_platform
+ def freeze_platform_and_update_repos
if released_changed? && released == true
- result = BuildServer.freeze(name)
+ result = BuildServer.freeze(name)
raise "Failed freeze platform #{name} with code #{result}" if result != BuildServer::SUCCESS
+ repositories.update_all(:publish_without_qa => false)
end
end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index e772a5808..132e6a6c9 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -5,6 +5,7 @@ class Project < ActiveRecord::Base
NAME_REGEXP = /[a-zA-Z0-9_\-\+\.]+/
belongs_to :owner, :polymorphic => true, :counter_cache => :own_projects_count
+ belongs_to :maintainer, :class_name => "User"
has_many :issues, :dependent => :destroy
has_many :pull_requests, :dependent => :destroy, :foreign_key => 'base_project_id'
@@ -22,12 +23,15 @@ class Project < ActiveRecord::Base
has_many :packages, :class_name => "BuildList::Package", :dependent => :destroy
has_and_belongs_to_many :advisories # should be without :dependent => :destroy
- validates :name, :uniqueness => {:scope => [:owner_id, :owner_type], :case_sensitive => false}, :presence => true, :format => {:with => /^#{NAME_REGEXP}$/, :message => I18n.t("activerecord.errors.project.uname")}
+ validates :name, :uniqueness => {:scope => [:owner_id, :owner_type], :case_sensitive => false},
+ :presence => true,
+ :format => {:with => /^#{NAME_REGEXP}$/, :message => I18n.t("activerecord.errors.project.uname")}
validates :owner, :presence => true
+ validates :maintainer_id, :presence => true, :unless => :new_record?
validates :visibility, :presence => true, :inclusion => {:in => VISIBILITIES}
validate { errors.add(:base, :can_have_less_or_equal, :count => MAX_OWN_PROJECTS) if owner.projects.size >= MAX_OWN_PROJECTS }
- attr_accessible :name, :description, :visibility, :srpm, :is_package, :default_branch, :has_issues, :has_wiki
+ attr_accessible :name, :description, :visibility, :srpm, :is_package, :default_branch, :has_issues, :has_wiki, :maintainer_id
attr_readonly :name, :owner_id, :owner_type
scope :recent, order("name ASC")
@@ -36,9 +40,19 @@ class Project < ActiveRecord::Base
scope :by_name, lambda {|name| where('projects.name ILIKE ?', name)}
scope :by_visibilities, lambda {|v| where(:visibility => v)}
scope :opened, where(:visibility => 'open')
- scope :addable_to_repository, lambda { |repository_id| where("projects.id NOT IN (SELECT project_to_repositories.project_id FROM project_to_repositories WHERE (project_to_repositories.repository_id = #{ repository_id }))") }
+ scope :package, where(:is_package => true)
+ scope :addable_to_repository, lambda { |repository_id| where %Q(
+ projects.id NOT IN (
+ SELECT
+ ptr.project_id
+ FROM
+ project_to_repositories AS ptr
+ WHERE (ptr.repository_id = #{ repository_id })
+ )
+ ) }
- after_create :attach_to_personal_repository
+ before_create :set_maintainer
+ after_save :attach_to_personal_repository
has_ancestry :orphan_strategy => :rootify #:adopt not available yet
@@ -63,8 +77,12 @@ class Project < ActiveRecord::Base
name
end
+ def all_members
+ members | (owner_type == 'User' ? [owner] : owner.members)
+ end
+
def members
- collaborators + groups.map(&:members).flatten
+ collaborators | groups.map(&:members).flatten
end
def platforms
@@ -121,6 +139,8 @@ class Project < ActiveRecord::Base
c.parent_id = id
c.owner = new_owner
c.updated_at = nil; c.created_at = nil # :id = nil
+ # Hack to call protected method :)
+ c.send :set_maintainer
c.save
end
end
@@ -129,6 +149,10 @@ class Project < ActiveRecord::Base
I18n.t("layout.projects.human_average_build_time", {:hours => (average_build_time/3600).to_i, :minutes => (average_build_time%3600/60).to_i})
end
+ def formatted_average_build_time
+ "%02d:%02d" % [average_build_time / 3600, average_build_time % 3600 / 60]
+ end
+
def xml_rpc_create(repository)
result = BuildServer.create_project name, repository.platform.name, repository.name, path
if result == BuildServer::SUCCESS
@@ -150,6 +174,16 @@ class Project < ActiveRecord::Base
protected
def attach_to_personal_repository
- repositories << self.owner.personal_repository if !repositories.exists?(:id => self.owner.personal_repository)
+ owner_rep = self.owner.personal_repository
+ if is_package
+ repositories << owner_rep unless repositories.exists?(:id => owner_rep)
+ else
+ repositories.delete owner_rep
+ end
end
+
+ def set_maintainer
+ self.maintainer_id = (owner_type == 'User') ? self.owner_id : self.owner.owner_id
+ end
+
end
diff --git a/app/models/register_request.rb b/app/models/register_request.rb
index 972dc1029..b40e7f4b4 100644
--- a/app/models/register_request.rb
+++ b/app/models/register_request.rb
@@ -1,16 +1,17 @@
# -*- encoding : utf-8 -*-
class RegisterRequest < ActiveRecord::Base
+
default_scope order('created_at ASC')
scope :rejected, where(:rejected => true)
scope :approved, where(:approved => true)
scope :unprocessed, where(:approved => false, :rejected => false)
+ validates :email, :presence => true, :uniqueness => {:case_sensitive => false}, :format => { :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i }
+
# before_create :generate_token
before_update :invite_approve_notification
- validates :email, :presence => true, :uniqueness => {:case_sensitive => false}, :format => { :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i }
-
def approve
update_attributes(:approved => true, :rejected => false)
end
@@ -26,7 +27,7 @@ class RegisterRequest < ActiveRecord::Base
end
def invite_approve_notification
- if approved_changed? and approved == true
+ if approved_changed? && approved?
generate_token
UserMailer.invite_approve_notification(self).deliver
end
diff --git a/app/models/relation.rb b/app/models/relation.rb
index 5e5e5bb5e..76829a849 100644
--- a/app/models/relation.rb
+++ b/app/models/relation.rb
@@ -10,9 +10,9 @@ class Relation < ActiveRecord::Base
before_validation :add_default_role
scope :by_user_through_groups, lambda {|u| where("actor_type = 'User' AND actor_id = ? OR actor_type = 'Group' AND actor_id IN (?)", u.id, u.group_ids)}
- scope :by_actor, lambda {|obj| {:conditions => ['actor_id = ? AND actor_type = ?', obj.id, obj.class.to_s]}}
- scope :by_target, lambda {|tar| {:conditions => ['target_id = ? AND target_type = ?', tar.id, tar.class.to_s]}}
- scope :by_role, lambda {|role| {:conditions => ['role = ?', role]}}
+ scope :by_actor, lambda {|obj| where(:actor_id => obj.id, :actor_type => obj.class.to_s)}
+ scope :by_target, lambda {|tar| where(:target_id => tar.id, :target_type => tar.class.to_s)}
+ scope :by_role, lambda {|role| where(:role => role)}
def self.create_with_role(actor, target, role)
r = self.new
@@ -22,6 +22,20 @@ class Relation < ActiveRecord::Base
r.save
end
+ def self.add_member(member, target, role)
+ if target.relations.exists?(:actor_id => member.id, :actor_type => member.class.to_s) || @platform.try(:owner) == member
+ true
+ else
+ rel = target.relations.build(:role => role)
+ rel.actor = member
+ rel.save
+ end
+ end
+
+ def self.remove_member(member, target)
+ Relation.by_actor(member).by_target(target).each{|r| r.destroy}
+ end
+
protected
def add_default_role
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 491d219e8..cd28fe6ec 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -2,6 +2,11 @@
class Repository < ActiveRecord::Base
belongs_to :platform
+
+ has_many :relations, :as => :target, :dependent => :destroy
+ has_many :actors, :as => :target, :class_name => 'Relation', :dependent => :destroy
+ has_many :members, :through => :actors, :source => :actor, :source_type => 'User'
+
has_many :project_to_repositories, :dependent => :destroy, :validate => true
has_many :projects, :through => :project_to_repositories
has_one :key_pair, :dependent => :destroy
@@ -14,7 +19,7 @@ class Repository < ActiveRecord::Base
before_create :xml_rpc_create, :unless => lambda {Thread.current[:skip]}
before_destroy :xml_rpc_destroy, :unless => lambda {Thread.current[:skip]}
- attr_accessible :name, :description
+ attr_accessible :name, :description, :publish_without_qa
attr_readonly :name, :platform_id
def base_clone(attrs = {})
@@ -38,6 +43,14 @@ class Repository < ActiveRecord::Base
end
end
+ def add_member(member, role = 'admin')
+ Relation.add_member(member, self, role)
+ end
+
+ def remove_member(member)
+ Relation.remove_member(member, self)
+ end
+
class << self
def build_stub(platform)
rep = Repository.new
diff --git a/app/models/subscribe.rb b/app/models/subscribe.rb
index 8b6907d98..8145286e1 100644
--- a/app/models/subscribe.rb
+++ b/app/models/subscribe.rb
@@ -34,7 +34,7 @@ class Subscribe < ActiveRecord::Base
def self.set_subscribe_to_commit(options, status)
if subscribe = Subscribe.where(options).first
- subscribe.update_attribute(:status, status)
+ subscribe.update_attributes(:status => status)
else
Subscribe.create(options.merge(:status => status))
end
diff --git a/app/models/user.rb b/app/models/user.rb
index c807cfbac..027175d5c 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -52,6 +52,10 @@ class User < ActiveRecord::Base
scope :admin, where(:role => 'admin')
scope :real, where(:role => ['', nil])
+ scope :member_of_project, lambda {|item|
+ where "#{table_name}.id IN (?)", item.members.map(&:id).uniq
+ }
+
after_create lambda { self.create_notifier }
before_create :ensure_authentication_token
diff --git a/app/presenters/comment_presenter.rb b/app/presenters/comment_presenter.rb
index bab0b3343..687316cc5 100644
--- a/app/presenters/comment_presenter.rb
+++ b/app/presenters/comment_presenter.rb
@@ -9,7 +9,7 @@ class CommentPresenter < ApplicationPresenter
@user = comment.user
@options = opts
- @content = simple_format(@comment.body, {}, :sanitize => true).html_safe
+ @content = @comment.body
end
def expandable?
@@ -40,7 +40,8 @@ class CommentPresenter < ApplicationPresenter
res = []
if controller.can? :update, @comment
- res << link_to(t("layout.edit"), ep).html_safe
+ res << link_to(t('layout.comments.md_cheatsheet_header'), '#md_help', 'data-toggle' => 'modal')
+ res << link_to(t("layout.edit"), ep, :id => "comment-#{comment.id}", :class => "edit_comment").html_safe
end
if controller.can? :delete, @comment
res << link_to(t("layout.delete"), dp, :method => "delete",
diff --git a/app/presenters/maintainer_presenter.rb b/app/presenters/maintainer_presenter.rb
new file mode 100644
index 000000000..186266061
--- /dev/null
+++ b/app/presenters/maintainer_presenter.rb
@@ -0,0 +1,43 @@
+class MaintainerPresenter < ApplicationPresenter
+
+ attr_reader :package, :package_link, :package_name, :package_type,
+ :package_version, :package_release, :package_version_release,
+ :package_updated_at
+ attr_reader :maintainer, :maintainer_fullname, :maintainer_email,
+ :maintainer_link, :maintainer_mail_link
+ delegate :package_type, :to => :package
+
+ [:name, :version, :release, :updated_at].each do |meth|
+ define_method "package_#{meth}" do
+ @package.send meth
+ end
+ end
+
+ [:fullname, :email].each do |meth|
+ define_method "maintainer_#{meth}" do
+ @maintainer.send meth
+ end
+ end
+
+ def initialize(package, opts = {})
+ @package = package
+ @maintainer = package.try(:assignee)
+ end
+
+ def package_link
+ link_to @package.name, @package.project
+ end
+
+ def package_version_release
+ "#{@package.version}-#{@package.release}"
+ end
+
+ def maintainer_link
+ link_to @maintainer.fullname, @maintainer
+ end
+
+ def maintainer_email_link
+ mail_to @maintainer.email, @maintainer.email, :encode => "javascript"
+ end
+
+end
diff --git a/app/views/advisories/_list.html.haml b/app/views/advisories/_list.html.haml
index c19ff66b9..5f3ea4f52 100644
--- a/app/views/advisories/_list.html.haml
+++ b/app/views/advisories/_list.html.haml
@@ -1,4 +1,4 @@
-%table#myTable.tablesorter.advisories{:cellspacing => "0", :cellpadding => "0"}
+%table#myTable.tablesorter.advisories.static-search{:cellspacing => "0", :cellpadding => "0"}
%thead
%tr
%th.th1= t("activerecord.attributes.advisory.advisory_id")
diff --git a/app/views/groups/profile/show.html.haml b/app/views/groups/profile/show.html.haml
index 8525cffe3..a67abf0e8 100644
--- a/app/views/groups/profile/show.html.haml
+++ b/app/views/groups/profile/show.html.haml
@@ -3,7 +3,7 @@
%h3= @group.name
%h4= t("activerecord.attributes.group.description") + ":"
%p= @group.description
- %h4= t("layout.groups.projects_list") + ":"
+ %h4= t("layout.groups.public_projects_list") + ":"
%p
- @projects.each do |project|
= link_to project.name, project
diff --git a/app/views/layouts/tour.html.haml b/app/views/layouts/tour.html.haml
index 1f0a486bc..c02d56642 100644
--- a/app/views/layouts/tour.html.haml
+++ b/app/views/layouts/tour.html.haml
@@ -34,6 +34,7 @@
.a= link_to t('layout.logout'), destroy_user_session_path, :method => :delete
- else
.user
+ .profile= link_to t("layout.devise.shared_links.sign_up"), new_register_request_path
.profile= link_to t("layout.devise.shared_links.sign_in"), new_user_session_path
.right
.both
@@ -55,4 +56,4 @@
bg_alpha : 0.5,
piro_scroll : true //pirobox always positioned at the center of the page
});
- });
\ No newline at end of file
+ });
diff --git a/app/views/platforms/base/_sidebar.html.haml b/app/views/platforms/base/_sidebar.html.haml
index 35916f520..eda999eeb 100644
--- a/app/views/platforms/base/_sidebar.html.haml
+++ b/app/views/platforms/base/_sidebar.html.haml
@@ -10,13 +10,16 @@
= link_to t("layout.platforms.about"), platform_path(@platform)
%li{:class => (contr == :repositories) ? 'active' : ''}
= link_to t("layout.repositories.list_header"), platform_repositories_path(@platform)
+ - if can? :show, @platform
+ %li{:class => (act == :index && contr == :maintainers) ? 'active' : nil}
+ = link_to t("layout.platforms.maintainers"), platform_maintainers_path(@platform)
- if can? :edit, @platform
%li{:class => (contr == :mass_builds && [:index, :create].include?(act)) ? 'active' : ''}
= link_to t("layout.platforms.mass_build"), platform_mass_builds_path(@platform)
- if can? :read, @platform.products.build
%li{:class => (contr == :products) ? 'active' : ''}
= link_to t("layout.products.list_header"), platform_products_path(@platform)
- - if can? :read_advisories, @platform
+ - if can? :advisories, @platform
%li{:class => (contr == :platforms and act == :advisories) ? 'active' : ''}
= link_to t("layout.advisories.list_header"), advisories_platform_path(@platform)
- if can? :update, @platform
diff --git a/app/views/platforms/maintainers/_list.html.haml b/app/views/platforms/maintainers/_list.html.haml
new file mode 100644
index 000000000..6effeb766
--- /dev/null
+++ b/app/views/platforms/maintainers/_list.html.haml
@@ -0,0 +1,25 @@
+%table#myTable.tablesorter.platform-maintainers.static-search{:cellspacing => "0", :cellpadding => "0"}
+ %thead
+ %tr
+ %th.centered= t("activerecord.attributes.maintainer.package_name")
+ %th.centered= t("activerecord.attributes.maintainer.package_type")
+ %th.centered= t("activerecord.attributes.maintainer.version")
+ %th.centered{:colspan => 2}= t("activerecord.models.maintainer")
+ %th.centered= t("activerecord.attributes.maintainer.updated_at")
+ %tr.search
+ -# TODO: change filter to Backbone.js
+ %th{:colspan => 6, :rowspan => 1}
+ = form_tag platform_maintainers_path(@platform), :method => :get do |f|
+ = text_field_tag('q', params[:q], :placeholder => t("layout.maintainers.search_by_package"), :class => params[:q].present? ? 'black' : 'gray')
+ %input{:type => 'submit', :value => t("layout.search.header")}
+ = button_to t('layout.clear'), {:action => :index} , :method => :get
+
+ %tbody
+ - MaintainerPresenter.present_collection(@maintainers) do |pr|
+ %tr{:class => cycle("odd", "even")}
+ %td= pr.package_link
+ %td= pr.package_type
+ %td= pr.package_version_release
+ %td= pr.maintainer_link
+ %td= pr.maintainer_email_link.html_safe
+ %td= pr.package_updated_at
diff --git a/app/views/platforms/maintainers/assignee.js.erb b/app/views/platforms/maintainers/assignee.js.erb
new file mode 100644
index 000000000..b36cdfcac
--- /dev/null
+++ b/app/views/platforms/maintainers/assignee.js.erb
@@ -0,0 +1 @@
+doHandleAbfAssignee(<%= @ret.to_json.html_safe %>);
diff --git a/app/views/platforms/maintainers/index.html.haml b/app/views/platforms/maintainers/index.html.haml
new file mode 100644
index 000000000..fd52033d6
--- /dev/null
+++ b/app/views/platforms/maintainers/index.html.haml
@@ -0,0 +1,7 @@
+-set_meta_tags :title => [title_object(@platform), t('layout.maintainers.list_header')]
+-# FIXME: no these 'base' links!
+= render 'platforms/base/submenu'
+= render 'platforms/base/sidebar'
+= render :partial => 'list', :object => @maintainers
+= will_paginate @maintainers
+
diff --git a/app/views/platforms/platforms/members.html.haml b/app/views/platforms/platforms/members.html.haml
index 712747edf..89bd0bedd 100644
--- a/app/views/platforms/platforms/members.html.haml
+++ b/app/views/platforms/platforms/members.html.haml
@@ -2,42 +2,9 @@
= render 'submenu'
= render 'sidebar'
-= form_tag remove_members_platform_path(@platform), :id => 'members_form', :method => :post do
- %table.tablesorter{:cellpadding => "0", :cellspacing => "0"}
- %thead
- %tr
- - if can? :remove_members, @platform
- %th
- \
- %th
- = t("layout.collaborators.members")
- - if can? :remove_member, @platform
- %th.buttons
- = t("layout.remove")
- %tbody
- - @members.select{|u| u != @platform.owner}.each_with_index do |user, num|
- %tr{:id => "admin-table-members-row#{num}", :class => cycle(:odd, :even)}
- - if can? :remove_members, @platform
- %td
- %span.niceCheck-main{:id => "niceCheckbox#{num}", :style => "background-position: 0px 0px; "}
- = check_box_tag "user_remove[#{user.id}][]"
- %td
- .img
- = image_tag avatar_url(user)
- .forimg= link_to user.fullname, user_path(user)
- - if can? :remove_member, @platform
- %td.buttons
- = link_to remove_member_platform_path(@platform, :member_id => user.id), :method => :delete, :confirm => t("layout.confirm") do
- %span.delete
- - if can? :remove_memvers, @platforms
- = submit_tag t("layout.delete"), :class => 'button'
- .both
-
-- if can? :add_member, @platform
- .hr.top
- = form_tag add_member_platform_path(@platform) do
- .admin-search
- = autocomplete_field_tag 'member_id', params[:member_id], autocomplete_user_uname_users_path, :id_element => '#member_id_field'
- = hidden_field_tag 'member_id', nil, :id => 'member_id_field'
- = submit_tag t("layout.add"), :class => 'button'
- .both
+= render "shared/members_table",
+ :remove_members_path => remove_members_platform_path(@platform),
+ :remove_member_path => remove_member_platform_path(@platform),
+ :add_member_path => add_member_platform_path(@platform),
+ :members => @members.select{|u| u != @platform.owner},
+ :editable_object => @platform
diff --git a/app/views/platforms/repositories/_form.html.haml b/app/views/platforms/repositories/_form.html.haml
index 2539464d6..065e99e24 100644
--- a/app/views/platforms/repositories/_form.html.haml
+++ b/app/views/platforms/repositories/_form.html.haml
@@ -1,9 +1,13 @@
-.leftlist= f.label :name, t("activerecord.attributes.repository.name"), :class => :label
-.rightlist= f.text_field :name, :class => 'text_field'
+- unless ['edit', 'update'].include? controller.action_name
+ .leftlist= f.label :name, t("activerecord.attributes.repository.name"), :class => :label
+ .rightlist= f.text_field :name, :class => 'text_field'
.leftlist= f.label :description, t("activerecord.attributes.repository.description"), :class => :label
.rightlist= f.text_field :description, :class => 'text_field'
+.leftlist= f.label :publish_without_qa, t("activerecord.attributes.repository.publish_without_qa"), :class => :label
+.rightlist= f.check_box :publish_without_qa, :class => 'check_box'
+
.both
.button_block
diff --git a/app/views/platforms/repositories/_list.html.haml b/app/views/platforms/repositories/_list.html.haml
index 69ef431d5..a1a4371f7 100644
--- a/app/views/platforms/repositories/_list.html.haml
+++ b/app/views/platforms/repositories/_list.html.haml
@@ -3,7 +3,7 @@
%tr
%th.th1= t("activerecord.attributes.repository.name")
%th.th2= t("layout.repositories.projects")
- %th= t("layout.delete")
+ %th= t("activerecord.attributes.repository.publish_without_qa")
%tbody
- @repositories.each do |repository|
%tr{:class => cycle("odd", "even")}
@@ -11,7 +11,5 @@
= link_to repository.name, platform_repository_path(@platform, repository)
%td
= repository.projects.count
- %td.buttons
- - if can? :destroy, repository
- = link_to platform_repository_path(@platform, repository), :method => :delete, :confirm => t("layout.repositories.confirm_delete") do
- %span.delete
\ No newline at end of file
+ %td
+ = repository.publish_without_qa
\ No newline at end of file
diff --git a/app/views/platforms/repositories/edit.html.haml b/app/views/platforms/repositories/edit.html.haml
new file mode 100644
index 000000000..5a9f1b232
--- /dev/null
+++ b/app/views/platforms/repositories/edit.html.haml
@@ -0,0 +1,16 @@
+-set_meta_tags :title => [title_object(@repository), t('layout.repositories.edit')]
+= render 'submenu'
+= render 'sidebar'
+
+%h3.fix= "#{t("layout.repositories.about")}: #{@repository.name}"
+
+= form_for @repository, :url => platform_repository_path(@platform, @repository), :html => { :class => :form } do |f|
+ = render "form", :f => f
+%br
+
+= render "shared/members_table",
+ :remove_members_path => remove_members_platform_repository_path(@platform, @repository),
+ :remove_member_path => remove_member_platform_repository_path(@platform, @repository),
+ :add_member_path => add_member_platform_repository_path(@platform, @repository),
+ :members => @members,
+ :editable_object => @repository
diff --git a/app/views/platforms/repositories/show.html.haml b/app/views/platforms/repositories/show.html.haml
index 5540913de..5bc491bfe 100644
--- a/app/views/platforms/repositories/show.html.haml
+++ b/app/views/platforms/repositories/show.html.haml
@@ -2,10 +2,15 @@
= render 'submenu'
= render 'sidebar'
-%h3.fix= "#{t("layout.repositories.about")}: #{@repository.name}"
+%h3 #{t("layout.repositories.about")} #{@repository.name}
%p= @repository.description
+.buttons_block
+ - if can? :update, @repository
+ = link_to image_tag("code.png", :alt => t("layout.edit")) + " " + t("layout.edit"), edit_platform_repository_path(@platform, @repository), :class => "button"
+ - if can? :destroy, @repository
+ = link_to image_tag("x.png", :alt => t("layout.delete")) + " " + t("layout.delete"), platform_repository_path(@platform, @repository), :method => "delete", :class => "button", :confirm => t("layout.repositories.confirm_delete")
%br
%br
%h3.fix= t("layout.projects.list_header")
diff --git a/app/views/projects/base/_repo_block.html.haml b/app/views/projects/base/_repo_block.html.haml
index f301d63b3..d8788f420 100644
--- a/app/views/projects/base/_repo_block.html.haml
+++ b/app/views/projects/base/_repo_block.html.haml
@@ -6,8 +6,9 @@
=image_tag 'zip.png', :alt => 'ZIP'
%b.caret
%ul.dropdown-menu
- %li=link_to "tar.gz", archive_path(project, @treeish, 'tar')
- %li=link_to "zip", archive_path(project, @treeish, 'zip')
+ - file_name = "#{@project.owner.uname}-#{@project.name}-#{@commit.id}"
+ %li=link_to "tar.gz", archive_path(project, file_name, 'tar.gz')
+ %li=link_to "zip", archive_path(project, file_name, 'zip')
= text_field_tag :url, git_repo_url(project.git_repo_name), :class => 'name', :spellcheck => 'false', :readonly => true
.git_help ?
diff --git a/app/views/projects/build_lists/_build_list.html.haml b/app/views/projects/build_lists/_build_list.html.haml
index 520023631..a5daa5d67 100644
--- a/app/views/projects/build_lists/_build_list.html.haml
+++ b/app/views/projects/build_lists/_build_list.html.haml
@@ -2,9 +2,14 @@
%td= link_to (build_list.bs_id.present? ? build_list.bs_id : t("layout.build_lists.bs_id_not_set")), build_list
%td
= build_list.human_status
+ %br
- if BuildList::HUMAN_STATUSES[build_list.status].in? [:build_pending, :build_started, :build_publish]
%time.js-relative-date{:datetime => build_list.updated_at.strftime("%FT%T%:z"), :title => build_list.updated_at.strftime("%F %T")}
= build_list.updated_at.strftime "%F %T"
+ - if build_list.build_started? && ((build_list.project.average_build_time || 0) > 0)
+ \/
+ %time
+ = build_list.project.formatted_average_build_time
- if build_list.project.present?
%td= link_to build_list.project.name_with_owner, build_list.project
%td= build_list_version_link(build_list)
diff --git a/app/views/projects/build_lists/_include_repos.html.haml b/app/views/projects/build_lists/_include_repos.html.haml
index 11ef89f97..504b73cee 100644
--- a/app/views/projects/build_lists/_include_repos.html.haml
+++ b/app/views/projects/build_lists/_include_repos.html.haml
@@ -1,4 +1,4 @@
- platform.repositories.each do |repo|
.both
- = check_box_tag "build_list[include_repos][]", repo.id, repo.name == 'main' || @project.repositories.map(&:id).include?(repo.id), :id => "include_repos_#{repo.id}", :save_to_platform_id => platform.id, :rep_name => repo.name
+ = check_box_tag "build_list[include_repos][]", repo.id, repo.name == 'main' || @project.repositories.map(&:id).include?(repo.id), :id => "include_repos_#{repo.id}", :rep_name => repo.name
= label_tag "include_repos_#{repo.id}", repo.name
diff --git a/app/views/projects/build_lists/_log.html.haml b/app/views/projects/build_lists/_log.html.haml
new file mode 100644
index 000000000..a2cd38da0
--- /dev/null
+++ b/app/views/projects/build_lists/_log.html.haml
@@ -0,0 +1,148 @@
+.hr
+%a{:name => 'log'}
+.log-wrapper
+ .log-header
+ .text-wrap
+ = link_to({:anchor => :log}, {:id => 'log_anchor'}) do
+ %h3= t("layout.build_lists.log.build_log")
+ %span
+ .both
+ .log-body.hidden
+ .reloader
+ %table.options
+ %tr.top
+ %td.first
+ = label_tag :word_wrap do
+ = check_box_tag :word_wrap
+ = t("layout.word_wrap")
+ %td.last{ :class => @build_list.build_started? ? nil : :hidden }
+ = label_tag :autoreload do
+ = check_box_tag :autoreload, true, @build_list.build_started?
+ = t("layout.build_lists.log.autoreload")
+ = select_tag :reload_interval, log_reload_time_options
+ %tr.bottom
+ %td.first
+ = link_to t("layout.build_lists.log.download"), build_list_log_url(:build), :id => :log_url
+ %td.last{ :class => @build_list.build_started? ? nil : :hidden }
+ = label_tag :load_lines do
+ = raw t("layout.build_lists.log.load_lines", :count => select_tag(:load_lines, log_reload_lines_options))
+ .both
+ %textarea.log{ :readonly => :readonly, :wrap => 'off',
+ :data => { :url => log_build_list_path(@build_list), :log_type => :build } }
+ = t("layout.build_lists.log.not_available")
+
+:javascript
+ $(function() {
+ (function() {
+ var $wrapper = $('div.log-wrapper');
+ var $logBody = $wrapper.children('div.log-body').first();
+ var $logCont = $logBody.children('.log').first();
+
+ var logUrl = $logCont.data('url');
+ var $logHead = $wrapper.children('div.log-header').first();
+
+ var $trigger = $logHead.children('span').first();
+ var $autoload = $('#autoreload');
+
+ var state = $logBody.is(':visible');
+ var t = null; // timer
+ var first_open = true;
+
+ if (state) {
+ $trigger.removeClass('closed');
+ $wrapper.removeClass('inactive')
+ .addClass('active');
+ } else {
+ $trigger.addClass('closed');
+ $logBody.addClass('hidden');
+ $wrapper.removeClass('active')
+ .addClass('inactive');
+ }
+
+ function getLineHeight(element){
+ var temp = document.createElement(element.nodeName);
+ temp.setAttribute("style","margin:0px;padding:0px;font-family:"+element.style.fontFamily+";font-size:"+element.style.fontSize);
+ temp.innerHTML = "test";
+ temp = element.parentNode.appendChild(temp);
+ var ret = temp.clientHeight;
+ temp.parentNode.removeChild(temp);
+ return ret;
+ }
+
+ var loadLog = function() {
+ $.ajax({
+ url: logUrl,
+ type: "GET",
+ dataType: 'json',
+ data: $logCont.data(),
+ beforeSend: function( xhr ) {
+ var token = $('meta[name="csrf-token"]').attr('content');
+ if (token) xhr.setRequestHeader('X-CSRF-Token', token);
+ },
+ success: function(data, textStatus, jqXHR) {
+ var l = $logCont[0];
+ var vScroll = l.scrollTop;
+ var hScroll = l.scrollLeft;
+ var onBottom = Math.abs((l.clientHeight + vScroll - l.scrollHeight)) < getLineHeight(l);
+
+ $logCont.text(data.log);
+
+ $logCont.scrollLeft(hScroll);
+ $logCont.scrollTop((onBottom || first_open) ? l.scrollHeight - l.clientHeight : vScroll);
+ first_open = false;
+ if (!data.building) $autoload.attr({'checked': false}).trigger('change');
+ }
+ });
+ }
+
+ var reloadChange = function() {
+ if ($(this).is(':checked')) {
+ first_open = true;
+ loadLog();
+ $logCont.scrollTop($logCont[0].scrollHeight - $logCont[0].clientHeight);
+ t = setInterval(function() {
+ loadLog();
+ }, $('#reload_interval').val());
+ } else {
+ clearInterval(t);
+ }
+ }
+
+ var toggleHandler = function() {
+ state = !state;
+ // if log opened
+ if (state) {
+ if ($autoload.is(':checked')) {
+ $autoload.trigger('change');
+ }
+ } else {
+ clearInterval(t);
+ }
+ $logBody.slideToggle('slow')
+ .toggleClass('hidden');
+ $logHead.toggleClass('active inactive');
+ $trigger.toggleClass('closed');
+
+ window.location.href = $('a#log_anchor').attr('href');
+ }
+
+ $wrapper.on('click', '.log-header > span', toggleHandler);
+ $autoload.on('change', reloadChange);
+
+ $('#word_wrap').on('change', function() {
+ $logCont.attr({'wrap': ($(this).is(':checked')) ? 'soft' : 'off'});
+ });
+
+ $('#reload_interval').on('change', function() {
+ clearInterval(t);
+ if ($autoload.is(':checked')) {
+ t = setInterval($(this).val());
+ }
+ });
+ $('#load_lines').on('change', function() {
+ $logCont.data('load_lines', $(this).val());
+ }).trigger('change');
+ loadLog();
+
+ })();
+ });
diff --git a/app/views/projects/build_lists/new.html.haml b/app/views/projects/build_lists/new.html.haml
index ccda36113..6a0c3fad6 100644
--- a/app/views/projects/build_lists/new.html.haml
+++ b/app/views/projects/build_lists/new.html.haml
@@ -6,12 +6,13 @@
- Platform.main.each do |pl|
- if pl.repository_ids.size > 0
.both
- = check_box_tag "build_for_platforms[]", pl.id, (params[:build_for_platforms]||[]).include?(pl.id.to_s), :class => 'build_bpl_ids', :id => "bpls_#{pl.id}", :'data-released' => pl.released ? 1 : 0
- = label_tag "bpls_#{pl.id}", pl.name
- .offset25{:style => 'padding-left: 25px'}= render 'include_repos', :platform => pl
+ =# check_box_tag "build_for_platforms[]", pl.id, (params[:build_for_platforms]||[]).include?(pl.id.to_s), :class => 'build_bpl_ids', :id => "bpls_#{pl.id}"
+ =# label_tag "bpls_#{pl.id}", pl.name
+ %div{:id => "build_for_pl_#{pl.id}", :class => 'build_for_pl'}= pl.name
+ .offset25= render 'include_repos', :platform => pl
%section.right
- %h3= t("activerecord.attributes.build_list.save_to_platform")
- .lineForm= f.select :save_to_platform_id, @project.repositories.collect{|r| ["#{r.platform.name}/#{r.name}", r.platform.id]}
+ %h3= t("activerecord.attributes.build_list.save_to_repository")
+ .lineForm= f.select :save_to_repository_id, @project.repositories.collect{|r| ["#{r.platform.name}/#{r.name}", r.id, {:publish_without_qa => r.publish_without_qa? ? 1 : 0, :platform_id => r.platform.id}]}
%h3= t("activerecord.attributes.build_list.project_version")
.lineForm= f.select :project_version, versions_for_group_select(@project), :selected => params[:build_list].try(:fetch, :project_version) || "latest_" + @project.default_branch
%h3= t("activerecord.attributes.build_list.arch")
diff --git a/app/views/projects/build_lists/show.html.haml b/app/views/projects/build_lists/show.html.haml
index 5ea60692a..b0f7f7f22 100644
--- a/app/views/projects/build_lists/show.html.haml
+++ b/app/views/projects/build_lists/show.html.haml
@@ -13,7 +13,6 @@
link_to("#{@build_list.save_to_platform.name}/#{@build_list.save_to_repository.name}",
[@build_list.save_to_platform, @build_list.save_to_repository])]
- elsif @build_list.container_path.present?
- - container_url = "http://#{request.host_with_port}/downloads#{@build_list.container_path}"
= link_to container_url, container_url
.both
@@ -125,8 +124,15 @@
var r = new Rosa.Routers.BuildListsAdvisoriesRouter();
});
- = submit_tag t("layout.publish"), :confirm => t("layout.confirm"), :name => 'publish' if @build_list.can_publish? && can?(:publish, @build_list)
- = submit_tag t("layout.reject_publish"), :confirm => t("layout.confirm"), :name => 'reject_publish' if @build_list.can_reject_publish? && can?(:reject_publish, @build_list)
+ - if BuildList::HUMAN_STATUSES[@build_list.status].in? [:build_started, :build_error, :success]
+ = render :partial => 'projects/build_lists/log'
+
+
+ - if (can_publish = @build_list.can_publish? && can?(:publish, @build_list))
+ .hr
+ = submit_tag t("layout.publish"), :confirm => t("layout.confirm"), :name => 'publish' if can_publish
+ - if @build_list.can_reject_publish? && can?(:reject_publish, @build_list)
+ = submit_tag t("layout.reject_publish"), :confirm => t("layout.confirm"), :name => 'reject_publish'
.hr
%h3= t("layout.build_lists.items_header")
diff --git a/app/views/projects/comments/_add.html.haml b/app/views/projects/comments/_add.html.haml
index e78fe2ac3..e0ab3eb65 100644
--- a/app/views/projects/comments/_add.html.haml
+++ b/app/views/projects/comments/_add.html.haml
@@ -1,4 +1,5 @@
#open-comment.comment.view
+ =link_to t('layout.comments.md_cheatsheet_header'), '#md_help', 'data-toggle' => 'modal', :style => 'float:right;'
%h3.tmargin0= t("layout.comments.new_header")
- if Comment.issue_comment?(commentable.class)
- new_path = project_issue_comments_path(project, commentable)
@@ -10,7 +11,7 @@
- subscribe_path = is_subscribed ? unsubscribe_commit_path(project, commentable) : subscribe_commit_path(project, commentable)
= form_for :comment, :url => new_path, :method => :post, :html => { :class => :form } do |f|
- = render "projects/comments/form", :f => f
+ = render "projects/comments/form", :f => f, :id => 'new'
.comment-left
= t("layout.comments.notifications_are")
%span.bold
diff --git a/app/views/projects/comments/_body.html.haml b/app/views/projects/comments/_body.html.haml
new file mode 100644
index 000000000..4b57f37b1
--- /dev/null
+++ b/app/views/projects/comments/_body.html.haml
@@ -0,0 +1,13 @@
+%ul.nav.nav-tabs#md_tabs
+ %li
+ %a{"data-toggle" => "tab", :href => "##{id}_edit"}=t 'layout.edit'
+ %li
+ %a{"data-toggle" => "tab", :href => "##{id}_preview"}=t 'layout.preview'
+
+.tab-content
+ .tab-pane.active{:id => "#{id}_edit"}
+ =f.text_area :body, :cols => 80, :id => "#{id}_edit_input"
+ =hidden_field_tag :body_dup, nil, :name => 'text', :id => "#{id}_edit_input_dup"
+ .tab-pane{:id => "#{id}_preview"}
+ .formatted.cm-s-default.md_and_cm
+
diff --git a/app/views/projects/comments/_form.html.haml b/app/views/projects/comments/_form.html.haml
index d7814ddad..f37286e42 100644
--- a/app/views/projects/comments/_form.html.haml
+++ b/app/views/projects/comments/_form.html.haml
@@ -1,2 +1,2 @@
-.wrapper= f.text_area :body, :cols => 80
-.comment-right= submit_tag t("layout.save")
\ No newline at end of file
+=render 'projects/comments/body', :f => f, :id => id
+.comment-right= submit_tag t("layout.save")
diff --git a/app/views/projects/comments/_list.html.haml b/app/views/projects/comments/_list.html.haml
index 8fc7adb93..e74842d82 100644
--- a/app/views/projects/comments/_list.html.haml
+++ b/app/views/projects/comments/_list.html.haml
@@ -3,4 +3,12 @@
%h3#block-list= t("layout.comments.comments_header")
- list.each do |comment|
- CommentPresenter.present(comment, :project => project, :commentable => commentable) do |presenter|
- = render 'shared/feed_message', :presenter => presenter
\ No newline at end of file
+ = render 'shared/feed_message', :presenter => presenter
+ #open-comment.comment.hidden{:class => "comment-#{comment.id}"}
+ %h3.tmargin0= t("layout.comments.edit_header")
+ = form_for comment, :url => project_commentable_comment_path(project, commentable, comment), :html => { :class => 'form edit_comment' } do |f|
+ = render "projects/comments/form", :f => f, :id => "edit_#{comment.id}"
+ .comment-left
+ =link_to t('layout.cancel'), '#', :id => "comment-#{comment.id}", :class => 'cancel_edit_comment button'
+ .both
+= render "projects/comments/markdown_help"
diff --git a/app/views/projects/comments/_markdown_help.html.haml b/app/views/projects/comments/_markdown_help.html.haml
new file mode 100644
index 000000000..28cf08dd8
--- /dev/null
+++ b/app/views/projects/comments/_markdown_help.html.haml
@@ -0,0 +1,86 @@
+#md_help.modal.hidden
+ .modal-header
+ %button.close{"aria-hidden" => "true", "data-dismiss" => "modal", :type => "button"} ×
+ %h3#myModalLabel=t('layout.comments.md_cheatsheet_header')
+ .modal-body
+ .mod
+ .col
+ %h3=t 'layout.comments.md_cheatsheet.format_text'
+ %p=t 'layout.comments.md_cheatsheet.headers'
+ %pre
+ -[1, 3, 6].each do |i|
+ ="#{'#'*i} This is an tag"
+ %p=t 'layout.comments.md_cheatsheet.text_styles'
+ %pre
+ :preserve
+ *This text will be italic*
+ _This will also be italic_
+ **This text will be bold**
+ __This will also be bold__
+ .col
+ %h3=t 'layout.comments.md_cheatsheet.lists'
+ %p=t 'layout.comments.md_cheatsheet.unordered'
+ %pre
+ :preserve
+ * Item 1
+ * Item 2
+ * Item 2a
+ * Item 2b
+ %p=t 'layout.comments.md_cheatsheet.ordered'
+ %pre
+ :preserve
+ 1. Item 1
+ 2. Item 2
+ 3. Item 3
+ * Item 3a
+ * Item 3b
+ .col
+ %h3=t 'layout.comments.md_cheatsheet.miscellaneous'
+ %p=t 'layout.comments.md_cheatsheet.images'
+ %pre
+ :preserve
+ ![avatar](/assets/ava.png)
+ Format: ![Alt Text](url)
+ %p=t 'layout.comments.md_cheatsheet.links'
+ %pre
+ :preserve
+ https://abf.rosalinux.ru
+ [ABF](https://abf.rosalinux.ru/)
+ %p=t 'layout.comments.md_cheatsheet.blockquotes'
+ %pre
+ :preserve
+ As Kanye West said:
+
+ > We're living the future so
+ > the present is our past.
+ .both
+ %hr.bootstrap
+ %h3=t 'layout.comments.md_cheatsheet.code_examples'
+ .col
+ %p
+ =t 'layout.comments.md_cheatsheet.syntax_highlighting'
+ %pre
+ :preserve
+ ```javascript
+ function fancyAlert(arg) {
+ if(arg) {
+ $.facebox({div:'#foo'})
+ }
+ }
+ ```
+ .col
+ %p=t 'layout.comments.md_cheatsheet.indent_code'
+ %pre
+ :preserve
+ Here is a Python code example
+ without syntax highlighting:
+
+ def foo:
+ if not bar:
+ return true
+ .col
+ %p=t 'layout.comments.md_cheatsheet.inline_code'
+ %pre
+ :preserve
+ I think you should use an
+ `[addr]` element here instead.
diff --git a/app/views/projects/comments/edit.html.haml b/app/views/projects/comments/edit.html.haml
index a27158367..0fd4907c1 100644
--- a/app/views/projects/comments/edit.html.haml
+++ b/app/views/projects/comments/edit.html.haml
@@ -8,4 +8,6 @@
= t("layout.comments.edit_header")
.inner
= form_for @comment, :url => project_commentable_comment_path(@project, @commentable, @comment), :html => {:class => :form} do |f|
- = render "form", :f => f
+ = render "form", :f => f, :id => "edit_#{@comment.id}"
+=hidden_field_tag :preview_url, project_md_preview_path(@project)
+
diff --git a/app/views/projects/git/commits/show.html.haml b/app/views/projects/git/commits/show.html.haml
index 28a008ac9..5cc736823 100644
--- a/app/views/projects/git/commits/show.html.haml
+++ b/app/views/projects/git/commits/show.html.haml
@@ -14,3 +14,6 @@
= render "projects/comments/list", :list => Comment.for_commit(@commit), :project => @project, :commentable => @commit
= render "projects/comments/add", :project => @project, :commentable => @commit if current_user
+
+=hidden_field_tag :preview_url, project_md_preview_path(@project)
+
diff --git a/app/views/projects/git/trees/empty.html.haml b/app/views/projects/git/trees/empty.html.haml
index 19edecbf5..228170179 100644
--- a/app/views/projects/git/trees/empty.html.haml
+++ b/app/views/projects/git/trees/empty.html.haml
@@ -30,7 +30,7 @@
%h3= t("layout.projects.git_global_setup")
%p
%code
- = "git config --global user.name #{current_user.fullname}"
+ = "git config --global user.name '#{current_user.fullname}'"
%br/
= "git config --global user.email #{current_user.email}"
%br/
diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml
index 72c9f4cc7..01b6a0a1a 100644
--- a/app/views/projects/issues/_form.html.haml
+++ b/app/views/projects/issues/_form.html.haml
@@ -1,8 +1,4 @@
-.leftlist= t('activerecord.attributes.issue.title') + ':'
-.rightlist= f.text_field :title
-.leftlist= t('activerecord.attributes.issue.body') + ':'
-.rightlist= f.text_area :body
-.both
+=render 'title_body', :f => f, :id => 'new'
.leftlist= t('activerecord.attributes.issue.assignee') + ':'
.rightlist
%span#people-span.small-text= t('layout.issues.choose_user_on_left')
diff --git a/app/views/projects/issues/_header.html.haml b/app/views/projects/issues/_header.html.haml
index 941755b54..3393fb965 100644
--- a/app/views/projects/issues/_header.html.haml
+++ b/app/views/projects/issues/_header.html.haml
@@ -9,19 +9,13 @@
%span.date=@issue.created_at.to_s(:long)
%br/
.both
- .fulltext.view.issue_body=@issue.body
+ .fulltext.view.issue_body.formatted.cm-s-default.md_and_cm=markdown @issue.body
.both
%br
- if can? :update, @issue
=link_to t('layout.edit'), '#', :id => 'edit_issue_content', :class => 'button'
=form_for :issue, :url => [@project, @issue], :method => :put, :html => { :class => 'edit_form issue', :style => 'display:none;' } do |f|
- .leftlist= t('activerecord.attributes.issue.title') + ':'
- .rightlist{:style => @issue.pull_request ? 'width: 500px;' : ''}
- = f.text_field :title
- .leftlist= t('activerecord.attributes.issue.body') + ':'
- .rightlist{:style => @issue.pull_request ? 'width: 500px;' : ''}
- = f.text_area :body
- .both
+ =render 'projects/issues/title_body', :f => f, :id => 'update'
=f.submit t('layout.update'), :id => 'update_issue_content'
=link_to t('layout.issues.cancel_button'), '#', :id => 'cancel_edit_issue_content', :class => 'button'
-%br
\ No newline at end of file
+%br
diff --git a/app/views/projects/issues/_labels.html.haml b/app/views/projects/issues/_labels.html.haml
index 81effb206..ebca53989 100644
--- a/app/views/projects/issues/_labels.html.haml
+++ b/app/views/projects/issues/_labels.html.haml
@@ -3,10 +3,10 @@
#labels-stock
=form_tag project_issues_path(@project), :id => 'filter_labels', :method => :get do
- @project.labels.each_with_index do |label, index|
- .div-tracker-labels{:id => "label-#{label.name}", :style => @labels.include?(label.name) ? "background-color:##{label.color};color:#FFF" : ''}
+ .div-tracker-labels{:id => "label-#{label.name.parameterize}", :style => @labels.include?(label.name) ? "background-color:##{label.color};color:#FFF" : ''}
.div-label-left
.label
- .flag{:id => "flag-#{label.name}", :style => "background-color: ##{label.color};"}
+ .flag{:id => "flag-#{label.name.parameterize}", :style => "background-color: ##{label.color};"}
.labeltext=label.name
=check_box_tag 'labels[]', label.name, @labels.include?(label.name), :style => 'display:none'
.both
diff --git a/app/views/projects/issues/_manage_sidebar.html.haml b/app/views/projects/issues/_manage_sidebar.html.haml
index 492265b57..9b819e38c 100644
--- a/app/views/projects/issues/_manage_sidebar.html.haml
+++ b/app/views/projects/issues/_manage_sidebar.html.haml
@@ -27,7 +27,7 @@
.avatar=image_tag avatar_url(@issue.assignee), :alt => 'avatar'
.name=@issue.assignee.fullname
.both
- =link_to(t('layout.issues.label_manage'), '#', :class => "button tmargin10 manage_assignee") if can_manage
+ =link_to(t('layout.issues.assignee_manage'), '#', :class => "button tmargin10 manage_assignee") if can_manage
- if can_manage
=form_tag search_collaborators_project_issues_path(@project), :id => 'search_user', :method => :get, :style => @issue.persisted? ? 'display:none' : '' do
=tracker_search_field(:search_user, t('layout.issues.search_user'))
@@ -47,6 +47,7 @@
.both=hidden_field_tag "flag#{label.id}", label.id, :name => "issue[labelings_attributes][#{label.id}][label_id]"
=form_for :issue, :url => [@project, @issue], :method => :put, :html => { :class => 'edit_labels issue'} do |f|
.manage_labels
+ =hidden_field_tag "update_labels", true
- @issue.labels.each do |label|
=hidden_field_tag "flag#{label.id}", label.id, :name => "issue[labelings_attributes][#{label.id}][label_id]"
- else
diff --git a/app/views/projects/issues/_title_body.html.haml b/app/views/projects/issues/_title_body.html.haml
new file mode 100644
index 000000000..806f9c16a
--- /dev/null
+++ b/app/views/projects/issues/_title_body.html.haml
@@ -0,0 +1,8 @@
+#open-comment.comment.view
+ %h3.tmargin0= t 'activerecord.attributes.issue.title'
+ .wrapper= f.text_area :title, :cols => 80, :rows => 1
+#open-comment.comment.view
+ =link_to t('layout.comments.md_cheatsheet_header'), '#md_help', 'data-toggle' => 'modal', :style => 'float:right;'
+ %h3.tmargin0= t 'activerecord.attributes.issue.body'
+ =render 'projects/comments/body', :f => f, :id => id
+.both
diff --git a/app/views/projects/issues/new.html.haml b/app/views/projects/issues/new.html.haml
index e3c4948e7..a59cc7a10 100644
--- a/app/views/projects/issues/new.html.haml
+++ b/app/views/projects/issues/new.html.haml
@@ -5,3 +5,6 @@
%h3.bpadding10= t("layout.issues.create_header")
= form_for :issue, :url => project_issues_path(@project), :html => { :class => 'form issue' } do |f|
= render "form", :f => f
+=hidden_field_tag :preview_url, project_md_preview_path(@project)
+= render "projects/comments/markdown_help"
+
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index 827eded43..6d8b4d06e 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -9,3 +9,6 @@
= render "projects/comments/list", :list => @issue.comments, :project => @project, :commentable => @issue
%br
= render "projects/comments/add", :project => @project, :commentable => @issue if current_user
+
+=hidden_field_tag :preview_url, project_md_preview_path(@project)
+
diff --git a/app/views/projects/projects/_form.html.haml b/app/views/projects/projects/_form.html.haml
index 9a7b90ba2..6bf9cb82a 100644
--- a/app/views/projects/projects/_form.html.haml
+++ b/app/views/projects/projects/_form.html.haml
@@ -6,14 +6,12 @@
.leftlist= f.label :description, t("activerecord.attributes.project.description"), :class => :label
.rightlist= f.text_area :description, :class => 'text_field', :cols => 80
.both
-- if ['new', 'create'].include? controller.action_name
+- if [:new, :create].include? act
.leftlist= f.label :owner_id, t("activerecord.attributes.project.owner"), :class => :label
.rightlist
= label_tag t("activerecord.attributes.project.who_owns.me")
- if Group.can_own_project(current_user).count > 0
= radio_button_tag :who_owns, 'me', @who_owns == :me #{}.merge( (@who_owns == :me) ? {:checked => 'checked'} : {} )
- - puts @who_owns.inspect
- - puts @who_owns == :group
= label_tag t("activerecord.attributes.project.who_owns.group")
= radio_button_tag :who_owns, 'group', @who_owns == :group #{}.merge( (@who_owns == :group) ? {:checked => 'checked'} : {} )
-# TODO: Make our own select_box helper with new design, blackjack and bitches!
@@ -33,19 +31,33 @@
= image_tag("lock.png")
= t("activerecord.attributes.project.visibilities.#{visibility}")
.both
+.leftlist
+ \
+.rightlist
+ .check
+ %span#niceCheckbox1.niceCheck-main= f.check_box :is_package#, :class => 'niceCheckbox1'
+ .forcheck= t("activerecord.attributes.project.is_package")
+ .both
+.both
- if [:edit, :update].include? act
.leftlist= t("activerecord.attributes.project.default_branch")
- .rightlist= f.select :default_branch, options_from_collection_for_select(@project.repo.branches, :name, :name, @project.default_branch), :class => 'sel80', :id => 'branch_selector'
- .both
-- if [:edit, :update].include? act
- .leftlist
- \
.rightlist
- .check
- %span#niceCheckbox1.niceCheck-main= f.check_box :is_package#, :class => 'niceCheckbox1'
- .forcheck= t("activerecord.attributes.project.is_package")
- .both
-.both
+ = f.select :default_branch,
+ options_from_collection_for_select( @project.repo.branches,
+ :name, :name, @project.default_branch),
+ :class => 'sel80', :id => 'branch_selector'
+ .both
+ #maintainer_form{:class => @project.is_package ? '' : 'hidden'}
+ = f.hidden_field :maintainer_id, :value => @project.maintainer_id
+ .leftlist
+ = t("activerecord.attributes.project.maintainer")
+ .rightlist
+ -# TODO: Maybe use something like Chosen with filter and prepopulated
+ -# list of potential maintainers?
+ = autocomplete_field_tag :maintainer_name, @project.maintainer.fullname,
+ autocomplete_maintainers_path(@project.owner, @project),
+ :id_element => '#project_maintainer_id',
+ :placeholder => @project.maintainer.fullname
- if [:new, :create].include? act
.leftlist= f.label :srpm, t("activerecord.attributes.project.srpm"), :class => :label
.rightlist= f.file_field :srpm, :class => 'file_field'
@@ -54,3 +66,7 @@
\
.rightlist= submit_tag t("layout.save"), :class => 'button'
.both
+:javascript
+ $(function() {
+ ( new Rosa.Views.ProjectModifyView ).render();
+ });
diff --git a/app/views/projects/pull_requests/show.html.haml b/app/views/projects/pull_requests/show.html.haml
index 630368568..30b30b592 100644
--- a/app/views/projects/pull_requests/show.html.haml
+++ b/app/views/projects/pull_requests/show.html.haml
@@ -15,3 +15,5 @@
.pull_status
=render 'status'
=render 'diff_commits_tabs' if @pull.status != 'already'
+=hidden_field_tag :preview_url, project_md_preview_path(@project)
+
diff --git a/app/views/shared/_feed_message.html.haml b/app/views/shared/_feed_message.html.haml
index 42b5d942a..0e7e8e420 100644
--- a/app/views/shared/_feed_message.html.haml
+++ b/app/views/shared/_feed_message.html.haml
@@ -19,5 +19,5 @@
- if presenter.content?
.fulltext{:class => "#{presenter.expandable? ? "hidden" : ''} #{presenter.caption? ? "" : "alone"}",
:id => presenter.expandable? ? "content-expand#{item_no}" : ''}
- = presenter.content
+ .cm-s-default.md_and_cm=markdown presenter.content
.both
diff --git a/app/views/shared/_members_table.html.haml b/app/views/shared/_members_table.html.haml
new file mode 100644
index 000000000..2b9ca7177
--- /dev/null
+++ b/app/views/shared/_members_table.html.haml
@@ -0,0 +1,39 @@
+= form_tag remove_members_path, :id => 'members_form', :method => :post do
+ %table.tablesorter{:cellpadding => "0", :cellspacing => "0"}
+ %thead
+ %tr
+ - if can? :remove_members, editable_object
+ %th
+ \
+ %th
+ = t("layout.collaborators.members")
+ - if can? :remove_member, editable_object
+ %th.buttons
+ = t("layout.remove")
+ %tbody
+ - members.each_with_index do |user, num|
+ %tr{:id => "admin-table-members-row#{num}", :class => cycle(:odd, :even)}
+ - if can? :remove_members, editable_object
+ %td
+ %span.niceCheck-main{:id => "niceCheckbox#{num}", :style => "background-position: 0px 0px; "}
+ = check_box_tag "user_remove[#{user.id}][]"
+ %td
+ .img
+ = image_tag avatar_url(user)
+ .forimg= link_to user.fullname, user_path(user)
+ - if can? :remove_member, editable_object
+ %td.buttons
+ = link_to "#{remove_member_path}?member_id=#{user.id}", :method => :delete, :confirm => t("layout.confirm") do
+ %span.delete
+ - if can? :remove_memvers, editable_object
+ = submit_tag t("layout.delete"), :class => 'button'
+ .both
+
+- if can? :add_member, editable_object
+ .hr.top
+ = form_tag add_member_path do
+ .admin-search
+ = autocomplete_field_tag 'member_id', params[:member_id], autocomplete_user_uname_users_path, :id_element => '#member_id_field'
+ = hidden_field_tag 'member_id', nil, :id => 'member_id_field'
+ = submit_tag t("layout.add"), :class => 'button'
+ .both
diff --git a/app/views/user_mailer/build_list_notification.en.haml b/app/views/user_mailer/build_list_notification.en.haml
new file mode 100644
index 000000000..9f58dafe3
--- /dev/null
+++ b/app/views/user_mailer/build_list_notification.en.haml
@@ -0,0 +1,15 @@
+%p
+ Build project
+ - if @build_list.project
+ = link_to @build_list.project.name_with_owner, project_url(@build_list.project)
+ - else
+ = t("layout.projects.unexisted_project")
+ completed with status
+ = @build_list.human_status
+ for arch
+ = "#{@build_list.arch.name}."
+%p
+ More detailed information you can get by link:
+ = link_to "task [№ #{@build_list.bs_id ? @build_list.bs_id : t("layout.build_lists.bs_id_not_set")}]", build_list_url(@build_list)
+
+%p== Support team «ROSA Build System»
diff --git a/app/views/user_mailer/build_list_notification.ru.haml b/app/views/user_mailer/build_list_notification.ru.haml
new file mode 100644
index 000000000..8a0970053
--- /dev/null
+++ b/app/views/user_mailer/build_list_notification.ru.haml
@@ -0,0 +1,15 @@
+%p
+ Сборка проекта
+ - if @build_list.project
+ = link_to @build_list.project.name_with_owner, project_url(@build_list.project)
+ - else
+ = t("layout.projects.unexisted_project")
+ завершена со статусом
+ = @build_list.human_status
+ для архитектуры
+ = "#{@build_list.arch.name}."
+%p
+ Более подробную информацию можно получить по ссылке:
+ = link_to "задание [№ #{@build_list.bs_id ? @build_list.bs_id : t("layout.build_lists.bs_id_not_set")}]", build_list_url(@build_list)
+
+%p== Команда поддержки «ROSA Build System»
diff --git a/app/views/user_mailer/invite_approve_notification.en.haml b/app/views/user_mailer/invite_approve_notification.en.haml
new file mode 100644
index 000000000..27a4ca11a
--- /dev/null
+++ b/app/views/user_mailer/invite_approve_notification.en.haml
@@ -0,0 +1,7 @@
+%p== Hello, #{@register_request.name || @register_request.email}.
+
+%p
+ You have been invited to project ABF. Please click on the following
+ = link_to 'link for registration', new_user_registration_url(:invitation_token => @register_request.token)
+
+%p== Support team «ROSA Build System»
diff --git a/app/views/user_mailer/invite_approve_notification.html.haml b/app/views/user_mailer/invite_approve_notification.html.haml
deleted file mode 100644
index 8d4bcc6bd..000000000
--- a/app/views/user_mailer/invite_approve_notification.html.haml
+++ /dev/null
@@ -1,7 +0,0 @@
-%p== Здравствуйте, #{@register_request.name || @register_request.email}.
-
-%p
- Вы приглашены в проект ABF. Чтобы зарегистрироваться перейдите по
- = link_to 'ссылке', new_user_registration_url(:invitation_token => @register_request.token)
-
-%p== Команда поддержки «ROSA Build System»
diff --git a/app/views/user_mailer/invite_approve_notification.ru.haml b/app/views/user_mailer/invite_approve_notification.ru.haml
new file mode 100644
index 000000000..e75296fe2
--- /dev/null
+++ b/app/views/user_mailer/invite_approve_notification.ru.haml
@@ -0,0 +1,7 @@
+%p== Здравствуйте, #{@register_request.name || @register_request.email}.
+
+%p
+ Вы приглашены в проект ABF. Пожалуйста, перейдите по
+ = link_to 'ссылке для регистрации', new_user_registration_url(:invitation_token => @register_request.token)
+
+%p== Команда поддержки «ROSA Build System»
diff --git a/app/views/users/profile/show.html.haml b/app/views/users/profile/show.html.haml
index bc6167a0c..3ab79e99f 100644
--- a/app/views/users/profile/show.html.haml
+++ b/app/views/users/profile/show.html.haml
@@ -6,13 +6,13 @@
%h3= title @user.uname
= @user.name
%br
- = link_to @user.email, "mailto:#{@user.email}"
+ = mail_to @user.email, @user.email, :encode => "javascript"
%br
%h4= t("activerecord.attributes.user.professional_experience") + ":"
%p= @user.professional_experience
%h4= t("layout.users.public_projects_list") + ":"
%p
- - @user.projects.by_visibilities(['open']).each do |project|
+ - @projects.each do |project|
= link_to project.name, project
%br
diff --git a/app/views/users/settings/_notifier.html.haml b/app/views/users/settings/_notifier.html.haml
new file mode 100644
index 000000000..83946d397
--- /dev/null
+++ b/app/views/users/settings/_notifier.html.haml
@@ -0,0 +1,3 @@
+.leftside.w25= f.check_box field
+.leftside= f.label field, t("activerecord.attributes.settings.notifier.#{field}")
+.both
diff --git a/app/views/users/settings/notifiers.html.haml b/app/views/users/settings/notifiers.html.haml
index 2d206c2aa..d5917480a 100644
--- a/app/views/users/settings/notifiers.html.haml
+++ b/app/views/users/settings/notifiers.html.haml
@@ -7,32 +7,16 @@
%br
= form_for @user.notifier, :url => notifiers_settings_path, :html => {:class => :form} do |f|
- .leftside.w25= f.check_box :can_notify
- .leftside= f.label :can_notify, t('activerecord.attributes.settings.notifier.can_notify')
- .both
+ = render 'notifier', :f => f, :field => :can_notify
%h3= t("layout.settings.notifiers.code_header")
- .leftside.w25= f.check_box :new_comment_commit_owner, :class => 'notify_cbx'
- .leftside= f.label :new_comment_commit_owner, t('activerecord.attributes.settings.notifier.new_comment_commit_owner')
- .both
- .leftside.w25= f.check_box :new_comment_commit_repo_owner, :class => 'notify_cbx'
- .leftside= f.label :new_comment_commit_repo_owner, t('activerecord.attributes.settings.notifier.new_comment_commit_repo_owner')
- .both
- .leftside.w25= f.check_box :new_comment_commit_commentor, :class => 'notify_cbx'
- .leftside= f.label :new_comment_commit_commentor, t('activerecord.attributes.settings.notifier.new_comment_commit_commentor')
- .both
+ - [:new_comment_commit_owner, :new_comment_commit_repo_owner, :new_comment_commit_commentor].each do |field|
+ = render 'notifier', :f => f, :field => field
%h3= t("layout.settings.notifiers.tracker_header")
- .leftside.w25= f.check_box :new_comment, :class => 'notify_cbx'
- .leftside= f.label :new_comment, t('activerecord.attributes.settings.notifier.new_comment')
- .both
- .leftside.w25= f.check_box :new_comment_reply, :class => 'notify_cbx'
- .leftside= f.label :new_comment_reply, t('activerecord.attributes.settings.notifier.new_comment_reply')
- .both
- .leftside.w25= f.check_box :new_issue, :class => 'notify_cbx'
- .leftside= f.label :new_issue, t('activerecord.attributes.settings.notifier.new_issue')
- .both
- .leftside.w25= f.check_box :issue_assign, :class => 'notify_cbx'
- .leftside= f.label :issue_assign, t('activerecord.attributes.settings.notifier.issue_assign')
- .both
+ - [:new_comment, :new_comment_reply, :new_issue, :issue_assign].each do |field|
+ = render 'notifier', :f => f, :field => field
+ %h3= t("layout.settings.notifiers.build_list_header")
+ - [:new_build, :new_associated_build].each do |field|
+ = render 'notifier', :f => f, :field => field
%br
.leftside.w25
diff --git a/config/deploy.rb b/config/deploy.rb
index 41f67ab13..c2581e0a9 100644
--- a/config/deploy.rb
+++ b/config/deploy.rb
@@ -55,7 +55,7 @@ namespace :deploy do
run "ln -nfs #{fetch :shared_path}/config/database.yml #{fetch :release_path}/config/database.yml"
# Setup application
- run "cp -n #{fetch :release_path}/config/deploy/application.#{fetch :stage}.yml #{fetch :shared_path}/config/application.yml"
+ run "cp -n #{fetch :release_path}/config/application.yml.sample #{fetch :shared_path}/config/application.yml"
run "ln -nfs #{fetch :shared_path}/config/application.yml #{fetch :release_path}/config/application.yml"
# It will survive downloads folder between deployments
@@ -101,3 +101,33 @@ namespace :rake_tasks do
mirror_rake_tasks 'db:seeds'
end
end
+
+namespace :update do
+ desc "Copy remote production shared files to localhost"
+ task :shared do
+ run_locally "rsync --recursive --times --rsh=ssh --compress --human-readable --progress #{user}@#{domain}:#{shared_path}/shared_contents/uploads public/uploads"
+ end
+
+ desc "Dump remote production postgresql database, rsync to localhost"
+ task :postgresql do
+ get("#{current_path}/config/database.yml", "tmp/database.yml")
+
+ remote_settings = YAML::load_file("tmp/database.yml")[rails_env]
+ local_settings = YAML::load_file("config/database.yml")["development"]
+
+
+ run "export PGPASSWORD=#{remote_settings["password"]} && pg_dump --host=#{remote_settings["host"]} --port=#{remote_settings["port"]} --username #{remote_settings["username"]} --file #{current_path}/tmp/#{remote_settings["database"]}_dump -Fc #{remote_settings["database"]}"
+
+ run_locally "rsync --recursive --times --rsh=ssh --compress --human-readable --progress #{user}@#{domain}:#{current_path}/tmp/#{remote_settings["database"]}_dump tmp/"
+
+ run_locally "dropdb -U #{local_settings["username"]} --host=#{local_settings["host"]} --port=#{local_settings["port"]} #{local_settings["database"]}"
+ run_locally "createdb -U #{local_settings["username"]} --host=#{local_settings["host"]} --port=#{local_settings["port"]} -T template0 #{local_settings["database"]}"
+ run_locally "pg_restore -U #{local_settings["username"]} --host=#{local_settings["host"]} --port=#{local_settings["port"]} -d #{local_settings["database"]} tmp/#{remote_settings["database"]}_dump"
+ end
+
+ desc "Dump all remote data to localhost"
+ task :all do
+ # update.shared
+ update.postgresql
+ end
+end
diff --git a/config/deploy/application.production.yml b/config/deploy/application.production.yml
deleted file mode 100644
index b4248563f..000000000
--- a/config/deploy/application.production.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-production:
- action_mailer_host: "abf.rosalinux.ru"
- root_path: /share
- nginx_log: /srv/rosa_build/shared/log/nginx.access.log
- do-not-reply-email: do-not-reply@rosalinux.ru
- project_name: ABF
- repo_project_name: ABF
- build_server_ip: 127.0.0.1
- build_server_port: 12555
- build_server_path: /xmlrpc
- product_builder_ip:
- mdv: 192.168.122.144
- nau5: 192.168.122.203
- product_builder_port: 12554
- product_builder_path: /xmlrpc
- distr_types: ['mdv']
diff --git a/config/deploy/application.school.yml b/config/deploy/application.school.yml
deleted file mode 100644
index 891090c97..000000000
--- a/config/deploy/application.school.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-common: &common
- project_name: ABF
- repo_project_name: ABF
- distr_types: ['mdv', 'nau5', 'suse', 'deb']
- wiki_formats:
- markdown: "Markdown"
- textile: "Textile"
- org: "Org-mode"
-
-production:
- <<: *common
- action_mailer_host: "school.rosalab.ru"
- root_path: /share
- nginx_log: /srv/rosa_build/shared/log/nginx.access.log
- do-not-reply-email: do-not-reply@school.rosalab.ru
- build_server_ip: 127.0.0.1
- build_server_port: 12555
- build_server_path: /xmlrpc
- product_builder_ip:
- mdv: 192.168.122.19
- nau5: 192.168.122.203
- product_builder_port: 12554
- product_builder_path: /xmlrpc
diff --git a/config/deploy/application.staging.yml b/config/deploy/application.staging.yml
deleted file mode 100644
index 5e2c3e8a6..000000000
--- a/config/deploy/application.staging.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-production:
- action_mailer_host: "dev-abf.rosalinux.ru"
- root_path: /share
- nginx_log: /srv/rosa_build/shared/log/nginx.access.log
- do-not-reply-email: do-not-reply@dev-abf.rosalinux.ru
- project_name: ABF
- repo_project_name: ABF
- build_server_ip: 127.0.0.1
- build_server_port: 12555
- build_server_path: /xmlrpc
- product_builder_ip:
- mdv: 192.168.122.19
- nau5: 192.168.122.203
- product_builder_port: 12554
- product_builder_path: /xmlrpc
- distr_types: ['mdv', 'nau5']
diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb
index e9b053ba5..c421b2c2e 100644
--- a/config/initializers/mime_types.rb
+++ b/config/initializers/mime_types.rb
@@ -12,7 +12,8 @@ Mime::Type.register "text/plain", 'patch'
[["text/x-python", ['py'], '8bit'],
["text/x-rpm-spec", ['spec'], '8bit'],
["text/x-csrc", ['h', 'c'], '8bit'],
- ["text/x-c++src", ['cpp'], '8bit']
+ ["text/x-c++src", ['cpp'], '8bit'],
+ ["text/x-diff", ['diff'], '8bit']
].each do |type|
MIME::Types.add MIME::Type.from_array(type)
end
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 33cf8933b..6370f6eb9 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -47,6 +47,7 @@ en:
processing: working ...
invalid_content_type: incorrect type
atom_link_tag_title: Private feed for %{nickname} | %{app_name}
+ preview: Preview
settings:
label: Settings
@@ -57,6 +58,7 @@ en:
change_email_link: Change email address
code_header: Code
tracker_header: Tracker
+ build_list_header: Build List
devise:
shared_links:
@@ -178,6 +180,8 @@ en:
new_comment_commit_owner: Notify about comments to my commit
new_comment_commit_repo_owner: Notify about comments to my repository commits
new_comment_commit_commentor: Notify about comments after my commit
+ new_build: Notify about my build tasks
+ new_associated_build: Notify about associated with me build tasks
private_user:
login: Login
diff --git a/config/locales/layout.en.yml b/config/locales/layout.en.yml
index 5268e0cc3..d4fefe67b 100644
--- a/config/locales/layout.en.yml
+++ b/config/locales/layout.en.yml
@@ -1,6 +1,8 @@
en:
layout:
autoreload_page: Update page automatically
+ autoreload_log: Update log every
+ word_wrap: Word wrap
read_more: Read more
turned_on: on
turned_off: off
diff --git a/config/locales/layout.ru.yml b/config/locales/layout.ru.yml
index 29247306a..8dae4c389 100644
--- a/config/locales/layout.ru.yml
+++ b/config/locales/layout.ru.yml
@@ -1,6 +1,8 @@
ru:
layout:
autoreload_page: Автоматически обновлять страницу
+ word_wrap: Перенос строк
+ autoreload_log: Обновлять лог каждые
read_more: Читать дальше
turned_on: включены
turned_off: выключены
diff --git a/config/locales/models/activity_feed.en.yml b/config/locales/models/activity_feed.en.yml
index f047c89ab..8df4770b3 100644
--- a/config/locales/models/activity_feed.en.yml
+++ b/config/locales/models/activity_feed.en.yml
@@ -18,6 +18,7 @@ en:
new_user_notification: Registered on project «%{ project_name }»
issue_assign_notification: New task assigned
invite_approve_notification: Invitation to ABF
+ for_arch: for arch %{arch}.
bodies:
new_comment_notification:
diff --git a/config/locales/models/activity_feed.ru.yml b/config/locales/models/activity_feed.ru.yml
index 66466da28..60911a6c8 100644
--- a/config/locales/models/activity_feed.ru.yml
+++ b/config/locales/models/activity_feed.ru.yml
@@ -18,7 +18,7 @@ ru:
new_user_notification: Регистрация на проекте «%{ project_name }»
issue_assign_notification: Вам назначили задачу
invite_approve_notification: Приглашение в ABF
- build_task: Сборочное задание
+ for_arch: для архитектуры %{arch}.
bodies:
new_comment_notification:
diff --git a/config/locales/models/build_list.en.yml b/config/locales/models/build_list.en.yml
index 087269400..f29c7d7cb 100644
--- a/config/locales/models/build_list.en.yml
+++ b/config/locales/models/build_list.en.yml
@@ -18,8 +18,7 @@ en:
additional_repos: Additional repositories
include_repos: Included repositories
created_at: Created on
- save_to_platform: Platform
- save_to_repository: Repository
+ save_to_repository: Save to repository
build_for_platform: Build for platform
update_type: Update type
build_requires: Build with all the required packages
@@ -72,7 +71,7 @@ en:
main_data: Main data
human_current_duration: Build currently takes %{hours} h. %{minutes} min.
- human_duration: Builded in %{hours} h. %{minutes} min.
+ human_duration: Built in %{hours} h. %{minutes} min.
attached_advisory: Attached advisory
create_advisory: Create new advisory
@@ -118,6 +117,21 @@ en:
project_not_found: Project not found
project_version_not_found: Project version not found
+ log:
+ build_log: Build Log
+ not_available: Log not available yet.
+ download: Download log
+ autoreload: Update log every
+ load_lines: Load last %{count} lines
+
+ reload_times:
+ 10000: "10 s"
+ 30000: "30 s"
+ 60000: "1 m"
+ 300000: "5 m"
+ 600000: "10 m"
+ 900000: "15 m"
+
flash:
build_list:
saved: Build list for project version '%{project_version}', platform '%{build_for_platform}' and architecture '%{arch}' has been created successfully
diff --git a/config/locales/models/build_list.ru.yml b/config/locales/models/build_list.ru.yml
index bb6dfa8ae..2f81ba2d0 100644
--- a/config/locales/models/build_list.ru.yml
+++ b/config/locales/models/build_list.ru.yml
@@ -18,8 +18,7 @@ ru:
additional_repos: Дополнительные репозитории
include_repos: Подключаемые репозитории
created_at: Создан
- save_to_platform: Платформа
- save_to_repository: Репозиторий
+ save_to_repository: Сохранить в репозиторий
build_for_platform: Собрано для платформы
update_type: Критичность обновления
build_requires: Пересборка с зависимостями
@@ -117,6 +116,21 @@ ru:
project_not_found: проект не найден
project_version_not_found: версия не найдена
+ log:
+ build_log: Лог сборки
+ not_available: В настоящий момент лог недоступен.
+ download: Загрузить лог
+ autoreload: Обновлять лог каждые
+ load_lines: Загружать последние %{count} строк
+
+ reload_times:
+ 10000: "10 сек"
+ 30000: "30 сек"
+ 60000: "1 мин"
+ 300000: "5 мин"
+ 600000: "10 мин"
+ 900000: "15 мин"
+
flash:
build_list:
saved: Билд лист для версии '%{project_version}', платформы '%{build_for_platform}' и архитектуры '%{arch}' создан успешно
diff --git a/config/locales/models/comment.en.yml b/config/locales/models/comment.en.yml
index a1bcd69ec..845864a64 100644
--- a/config/locales/models/comment.en.yml
+++ b/config/locales/models/comment.en.yml
@@ -4,10 +4,26 @@ en:
confirm_delete: Are you sure you want to delete the comment?
new_header: New comment
edit_header: Editing a comment
- has_commented: "added a note"
- notifications_are: "Notifications for new comments are"
- comments_header: "Comments"
- back: 'Back'
+ has_commented: added a note
+ notifications_are: Notifications for new comments are
+ comments_header: Comments
+ back: Back
+ md_cheatsheet_header: Markdown Cheat Sheet
+ md_cheatsheet:
+ format_text: Format Text
+ headers: Headers
+ text_styles: Text styles
+ lists: Lists
+ unordered: Unordered
+ ordered: Ordered
+ miscellaneous: Miscellaneous
+ images: Images
+ links: Links
+ blockquotes: Blockquotes
+ code_examples: Code Examples in Markdown
+ syntax_highlighting: Syntax highlighting
+ indent_code: indent your code 4 spaces
+ inline_code: Inline code for comments
flash:
comment:
diff --git a/config/locales/models/comment.ru.yml b/config/locales/models/comment.ru.yml
index ff9e15dd3..89d87f2b4 100644
--- a/config/locales/models/comment.ru.yml
+++ b/config/locales/models/comment.ru.yml
@@ -4,17 +4,33 @@ ru:
confirm_delete: Вы уверены, что хотите удалить комментарий?
new_header: Новый комментарий
edit_header: Редактирование комментария
- has_commented: "оставил комментарий"
- notifications_are: "Уведомления о последующих комментариях"
- comments_header: "Комментарии"
- back: 'Назад'
+ has_commented: оставил комментарий
+ notifications_are: Уведомления о последующих комментариях
+ comments_header: Комментарии
+ back: Назад
+ md_cheatsheet_header: Шпаргалка по Markdown
+ md_cheatsheet:
+ format_text: Формат текста
+ headers: Заголовки
+ text_styles: Стиль текста
+ lists: Списки
+ unordered: Маркированный
+ ordered: Нумерованный
+ miscellaneous: Разное
+ images: Изображения
+ links: Ссылки
+ blockquotes: Цитирование
+ code_examples: Примеры кода в Markdown
+ syntax_highlighting: Подсветка синтаксиса
+ indent_code: Отступ кода на 4 пробела
+ inline_code: Встроенный код в строке
flash:
comment:
saved: Комментарий успешно сохранен
save_error: Ошибка сохранения комментария
destroyed: Комментарий удален
-
+
activerecord:
attributes:
comment:
diff --git a/config/locales/models/group.en.yml b/config/locales/models/group.en.yml
index f8e015de3..1cb6a06dc 100644
--- a/config/locales/models/group.en.yml
+++ b/config/locales/models/group.en.yml
@@ -16,6 +16,7 @@ en:
description: Descripton
leave_group: Leave group
projects_list: Projects list
+ public_projects_list: Public projects list
public_profile: Public profile
delete_warning: Attention! Deleted group can not be restored!
diff --git a/config/locales/models/group.ru.yml b/config/locales/models/group.ru.yml
index 01c5aaf7a..c43e33e2a 100644
--- a/config/locales/models/group.ru.yml
+++ b/config/locales/models/group.ru.yml
@@ -16,6 +16,7 @@ ru:
description: Описание
leave_group: Покинуть группу
projects_list: Список проектов
+ public_projects_list: Список публичных проектов
public_profile: Публичный профиль
delete_warning: Внимание! Удаленная группа восстановлению не подлежит.
diff --git a/config/locales/models/issue.en.yml b/config/locales/models/issue.en.yml
index bb6b3111d..d656ab48f 100644
--- a/config/locales/models/issue.en.yml
+++ b/config/locales/models/issue.en.yml
@@ -41,6 +41,7 @@ en:
update_label: Update label
label_custom_color: Custom color
label_manage: Manage labels
+ assignee_manage: Manage assignee
assignee: Assignee
search_user: Find user...
search_labels: Find labels...
diff --git a/config/locales/models/issue.ru.yml b/config/locales/models/issue.ru.yml
index 74745f91c..a4bca52ff 100644
--- a/config/locales/models/issue.ru.yml
+++ b/config/locales/models/issue.ru.yml
@@ -40,7 +40,8 @@ ru:
new_label: Название новой метки
update_label: Обновить метку
label_custom_color: Свой цвет
- label_manage: Управление
+ label_manage: Управление метками
+ assignee_manage: Назначить исполнителя
assignee: Исполнитель
search_user: Найти пользователя...
search_labels: Найти метки...
diff --git a/config/locales/models/maintainer.en.yml b/config/locales/models/maintainer.en.yml
new file mode 100644
index 000000000..92720e4a7
--- /dev/null
+++ b/config/locales/models/maintainer.en.yml
@@ -0,0 +1,25 @@
+en:
+ layout:
+ maintainers:
+ list_header: Maintainers
+ search_by_package: Search by package name
+
+ flash:
+ maintainer:
+ saved: Maintainer saved
+ created: Maintainer created
+ save_error: Maintainer saves error
+ create_error: Maintainer create error
+ destroyed: Maintainer deleted
+
+ activerecord:
+ models:
+ maintainer: Maintainer
+ attributes:
+ maintainer:
+ package_name: Package
+ package_type: Type
+ created_at: First Update
+ updated_at: Last Update
+ version: Version-Release
+
diff --git a/config/locales/models/maintainer.ru.yml b/config/locales/models/maintainer.ru.yml
new file mode 100644
index 000000000..04cd6f7b8
--- /dev/null
+++ b/config/locales/models/maintainer.ru.yml
@@ -0,0 +1,25 @@
+ru:
+ layout:
+ maintainers:
+ list_header: Майнтейнеры
+ search_by_package: Искать по имени пакета
+
+ flash:
+ maintainer:
+ saved: Майнтейнер успешно сохранен
+ created: Майнтейнер успешно добавлен
+ save_error: Не удалось сохранить майнтейнера
+ create_error: Не удалось создать майнтейнера
+ destroyed: Майнтейнер успешно удален
+
+ activerecord:
+ models:
+ maintainer: Майнтейнер
+ attributes:
+ maintainer:
+ package_name: Пакет
+ package_type: Тип
+ created_at: Создан
+ updated_at: Обновлен
+ version: Версия-Релиз
+
diff --git a/config/locales/models/platform.en.yml b/config/locales/models/platform.en.yml
index cf44b6550..9a828c31c 100644
--- a/config/locales/models/platform.en.yml
+++ b/config/locales/models/platform.en.yml
@@ -40,6 +40,7 @@ en:
target_platform: Target platform
target_architecture: Target architecture
members: Members
+ maintainers: Maintainers
project: Project
arch: Architecture
mass_build: Mass build
@@ -62,7 +63,6 @@ en:
cancel_mass_build: Mass build canceled
clone_success: Cloned successfully
members:
- already_added: "%{name} is already a member of platform"
successfully_added: "%{name} successfully added to the platform"
error_in_adding: "Unable to add %{name} as member"
diff --git a/config/locales/models/platform.ru.yml b/config/locales/models/platform.ru.yml
index 6c04bbca8..a71e49bdc 100644
--- a/config/locales/models/platform.ru.yml
+++ b/config/locales/models/platform.ru.yml
@@ -40,6 +40,7 @@ ru:
target_platform: Целевая платформа
target_architecture: Целевая архитектура
members: Участники
+ maintainers: Майнтейнеры
arch: Архитектура
mass_build: Массовая сборка
build_task: Сборочное задание
@@ -62,7 +63,6 @@ ru:
cancel_mass_build: Массовая сборка отменена
clone_success: Клонирование успешно
members:
- already_added: "%{name} уже является участником платформы"
successfully_added: "Участник %{name} успешно добавлен к платформе"
error_in_adding: "Не удалось добавить участника %{name}"
diff --git a/config/locales/models/product_build_list.en.yml b/config/locales/models/product_build_list.en.yml
index 0eabdae27..8b1b281e0 100644
--- a/config/locales/models/product_build_list.en.yml
+++ b/config/locales/models/product_build_list.en.yml
@@ -10,7 +10,7 @@ en:
'2': 'build in progress'
build_failed: Build failed
build_started: Build in progress
- build_completed: Builded
+ build_completed: Built
ownership:
header: Build list ownership
diff --git a/config/locales/models/project.en.yml b/config/locales/models/project.en.yml
index f284eadc1..a538a25f9 100644
--- a/config/locales/models/project.en.yml
+++ b/config/locales/models/project.en.yml
@@ -93,6 +93,8 @@ en:
group: Group
default_branch: Default branch
is_package: Project is a package
+ maintainer: Maintainer of project
+ maintainer_id: Maintainer of project
errors:
project:
uname: The name can only use lower case Latin letters (a-z), numbers (0-9) and underscore (_)
diff --git a/config/locales/models/project.ru.yml b/config/locales/models/project.ru.yml
index c05f18619..321fb777d 100644
--- a/config/locales/models/project.ru.yml
+++ b/config/locales/models/project.ru.yml
@@ -93,6 +93,8 @@ ru:
group: Группа
default_branch: Ветка по умолчанию
is_package: Проект является пакетом
+ maintainer_id: Майнтейнер проекта
+ maintainer: Майнтейнер проекта
errors:
project:
uname: В имени можно использовать только строчные символы латинского алфавита (a-z), цифры (0-9) и символ нижнего подчеркивания (_)
diff --git a/config/locales/models/repository.en.yml b/config/locales/models/repository.en.yml
index 7f8ad732b..5fe13700d 100644
--- a/config/locales/models/repository.en.yml
+++ b/config/locales/models/repository.en.yml
@@ -2,6 +2,7 @@ en:
layout:
repositories:
add_project_to: Add project to repository
+ edit: Settings
list: List
about: About repository
list_header: Repositories
@@ -29,13 +30,18 @@ en:
flash:
repository:
saved: Repository added
+ updated: Repository updated
save_error: Unable to add repository
+ update_error: Unable to update repository
destroyed: Repository deleted
project_added: Project added to repository
project_not_added: Project adding error. A project with such name already exists in this repository. Remove the old project first
project_removed: Project deleted
project_not_removed: Unable to delete project from repository
clear: Platform successfully cleared!
+ members:
+ successfully_added: "%{name} successfully added to the repository"
+ error_in_adding: "Unable to add %{name} as member"
activerecord:
models:
@@ -44,6 +50,7 @@ en:
repository:
name: Name
description: Description
+ publish_without_qa: Publication without QA
platform_id: Platform
platform: Platform
created_at: Created
diff --git a/config/locales/models/repository.ru.yml b/config/locales/models/repository.ru.yml
index b01307e1c..a35396fd9 100644
--- a/config/locales/models/repository.ru.yml
+++ b/config/locales/models/repository.ru.yml
@@ -2,6 +2,7 @@ ru:
layout:
repositories:
add_project_to: Добавить проект к репозиторию
+ edit: Настройки
list: Список
about: О репозитории
list_header: Репозитории
@@ -29,13 +30,18 @@ ru:
flash:
repository:
saved: Репозиторий успешно добавлен
+ updated: Репозиторий успешно обновлен
save_error: Не удалось добавить репозиторий
+ update_error: Не удалось обновить репозиторий
destroyed: Репозиторий успешно удален
project_added: Проект добавлен к репозиторию
project_not_added: Не удалось добавить проект. В этом репозитории уже есть проект с таким именем. Сначала нужно удалить старый проект
project_removed: Проект удален из репозитория
project_not_removed: Не удалось удалить проект из репозитория
clear: Платформа успешно очищена!
+ members:
+ successfully_added: "Участник %{name} успешно добавлен к репозиторию"
+ error_in_adding: "Не удалось добавить участника %{name}"
activerecord:
models:
@@ -44,6 +50,7 @@ ru:
repository:
name: Название
description: Описание
+ publish_without_qa: Публикация без участия QA
platform_id: Платформа
platform: Платформа
created_at: Создан
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index 3ca418329..e26b13393 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -47,6 +47,7 @@ ru:
processing: Обрабатывается...
invalid_content_type: имеет неверный тип
atom_link_tag_title: Приватная лента для %{nickname} | %{app_name}
+ preview: Предосмотр
settings:
label: 'Настройки'
@@ -57,6 +58,7 @@ ru:
change_email_link: Изменить адрес электронной почты
code_header: Код
tracker_header: Трекер задач
+ build_list_header: Сборочные задания
devise:
shared_links:
@@ -179,6 +181,8 @@ ru:
new_comment_commit_owner: Оповещать о комментариях к моему коммиту
new_comment_commit_repo_owner: Оповещать о комментариях к коммитам в моем репозитории
new_comment_commit_commentor: Оповещать о комментариях к коммиту после моего
+ new_build: Оповещать о моих сборочных заданиях
+ new_associated_build: Оповещать о связанных со мной сборочных заданиях
private_user:
login: Логин
diff --git a/config/routes.rb b/config/routes.rb
index a1525eef4..49cb74f1f 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -15,6 +15,7 @@ Rosa::Application.routes.draw do
get '/forbidden' => 'pages#forbidden', :as => 'forbidden'
get '/terms-of-service' => 'pages#tos', :as => 'tos'
get '/tour/:id' => 'pages#tour_inside', :as => 'tour_inside', :id => /projects|sources|builds/
+ match '/invite.html' => redirect('/register_requests/new')
get '/activity_feeds.:format' => 'activity_feeds#index', :as => 'atom_activity_feeds', :format => /atom/
if APP_CONFIG['anonymous_access']
@@ -55,7 +56,7 @@ Rosa::Application.routes.draw do
post :clear
get :clone
get :members
- post :remove_members
+ post :remove_members # fixme: change post to delete
delete :remove_member
post :add_member
post :make_clone
@@ -75,13 +76,16 @@ Rosa::Application.routes.draw do
get :add_project
delete :remove_project
get :projects_list
+ post :remove_members # fixme: change post to delete
+ delete :remove_member
+ post :add_member
end
end
resources :key_pairs, :only => [:create, :index, :destroy]
resources :products do
resources :product_build_lists, :only => [:create, :destroy]
end
-
+ resources :maintainers, :only => [:index]
end
match '/private/:platform_name/*file_path' => 'privates#show'
@@ -135,6 +139,7 @@ Rosa::Application.routes.draw do
resources :build_lists, :only => [:index, :show, :update] do
member do
put :cancel
+ get :log
end
collection { post :search }
end
@@ -185,9 +190,11 @@ Rosa::Application.routes.draw do
get :autocomplete_base_project, :on => :collection
put :merge, :on => :member
end
+ post '/preview' => 'projects#preview', :as => 'md_preview'
end
# Resource
+ get '/autocomplete_maintainers' => 'projects#autocomplete_maintainers', :as => :autocomplete_maintainers
get '/modify' => 'projects#edit', :as => :edit_project
put '/' => 'projects#update'
delete '/' => 'projects#destroy'
@@ -222,7 +229,7 @@ Rosa::Application.routes.draw do
# Raw
get '/raw/:treeish/*path' => "git/blobs#raw", :as => :raw, :format => false
# Archive
- get '/archive/:treeish.:format' => "git/trees#archive", :as => :archive, :format => /zip|tar/
+ get '/archive/:treeish.:format' => "git/trees#archive", :as => :archive, :format => /zip|tar\.gz/
end
end
end
diff --git a/db/migrate/20120306212914_add_project_to_comment.rb b/db/migrate/20120306212914_add_project_to_comment.rb
index 94b6f8361..1e8ef5abe 100644
--- a/db/migrate/20120306212914_add_project_to_comment.rb
+++ b/db/migrate/20120306212914_add_project_to_comment.rb
@@ -5,7 +5,7 @@ class AddProjectToComment < ActiveRecord::Migration
Subscribe.reset_column_information
Comment.where(:commentable_type => 'Grit::Commit').destroy_all
Comment.where(:commentable_type => 'Issue').each do |comment|
- comment.update_attribute(:project_id, comment.commentable.project)
+ comment.update_column(:project_id, comment.commentable.project.id)
end
end
diff --git a/db/migrate/20120601142035_add_name_platform_index_to_build_list_packages.rb b/db/migrate/20120601142035_add_name_platform_index_to_build_list_packages.rb
new file mode 100644
index 000000000..8e8cfee7d
--- /dev/null
+++ b/db/migrate/20120601142035_add_name_platform_index_to_build_list_packages.rb
@@ -0,0 +1,5 @@
+class AddNamePlatformIndexToBuildListPackages < ActiveRecord::Migration
+ def change
+ add_index :build_list_packages, [:name,:project_id]
+ end
+end
diff --git a/db/migrate/20120822130632_add_maintainer_id_to_projects.rb b/db/migrate/20120822130632_add_maintainer_id_to_projects.rb
new file mode 100644
index 000000000..94614ef56
--- /dev/null
+++ b/db/migrate/20120822130632_add_maintainer_id_to_projects.rb
@@ -0,0 +1,9 @@
+class AddMaintainerIdToProjects < ActiveRecord::Migration
+ def self.up
+ add_column :projects, :maintainer_id, :integer
+ end
+
+ def self.down
+ remove_column :projects, :maintainer_id
+ end
+end
diff --git a/db/migrate/20120822210712_add_actual_to_build_list_packages.rb b/db/migrate/20120822210712_add_actual_to_build_list_packages.rb
new file mode 100644
index 000000000..847eed97e
--- /dev/null
+++ b/db/migrate/20120822210712_add_actual_to_build_list_packages.rb
@@ -0,0 +1,14 @@
+class AddActualToBuildListPackages < ActiveRecord::Migration
+ def self.up
+ add_column :build_list_packages, :actual, :boolean, :default => false
+ add_index :build_list_packages, [:actual, :platform_id]
+ add_index :build_lists, [:project_id, :save_to_repository_id, :build_for_platform_id, :arch_id],
+ :name => :maintainer_search_index
+ end
+
+ def self.down
+ remove_index :build_list_packages, [:actual, :platform_id]
+ remove_column :build_list_packages, :actual
+ remove_index :build_lists, :name => :maintainer_search_index
+ end
+end
diff --git a/db/migrate/20120906115648_add_publish_without_qa_to_repositories.rb b/db/migrate/20120906115648_add_publish_without_qa_to_repositories.rb
new file mode 100644
index 000000000..c3f83e01e
--- /dev/null
+++ b/db/migrate/20120906115648_add_publish_without_qa_to_repositories.rb
@@ -0,0 +1,20 @@
+class AddPublishWithoutQaToRepositories < ActiveRecord::Migration
+
+ class Platform < ActiveRecord::Base
+ has_many :repositories, :dependent => :destroy
+ end
+
+ class Repository < ActiveRecord::Base
+ belongs_to :platform
+ end
+
+ def up
+ add_column :repositories, :publish_without_qa, :boolean, :default => true
+ Platform.where(:released => true).each{|p| p.repositories.update_all(:publish_without_qa => false)}
+ Platform.where(:released => false).each{|p| p.repositories.update_all(:publish_without_qa => true)}
+ end
+
+ def down
+ remove_column :repositories, :publish_without_qa
+ end
+end
diff --git a/db/migrate/20120910094748_add_language_to_register_request.rb b/db/migrate/20120910094748_add_language_to_register_request.rb
new file mode 100644
index 000000000..56b2dcfbd
--- /dev/null
+++ b/db/migrate/20120910094748_add_language_to_register_request.rb
@@ -0,0 +1,5 @@
+class AddLanguageToRegisterRequest < ActiveRecord::Migration
+ def change
+ add_column :register_requests, :language, :string
+ end
+end
diff --git a/db/migrate/20120914160741_add_build_list_notifications_to_settings_notifier.rb b/db/migrate/20120914160741_add_build_list_notifications_to_settings_notifier.rb
new file mode 100644
index 000000000..e94e14128
--- /dev/null
+++ b/db/migrate/20120914160741_add_build_list_notifications_to_settings_notifier.rb
@@ -0,0 +1,6 @@
+class AddBuildListNotificationsToSettingsNotifier < ActiveRecord::Migration
+ def change
+ add_column :settings_notifiers, :new_build, :boolean, :default => true
+ add_column :settings_notifiers, :new_associated_build, :boolean, :default => true
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 85a2d95b9..7d4175660 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20120730214052) do
+ActiveRecord::Schema.define(:version => 20120914160741) do
create_table "activity_feeds", :force => true do |t|
t.integer "user_id", :null => false
@@ -91,11 +91,14 @@ ActiveRecord::Schema.define(:version => 20120730214052) do
t.string "version"
t.string "release"
t.string "package_type"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ t.boolean "actual", :default => false
end
+ add_index "build_list_packages", ["actual", "platform_id"], :name => "index_build_list_packages_on_actual_and_platform_id"
add_index "build_list_packages", ["build_list_id"], :name => "index_build_list_packages_on_build_list_id"
+ add_index "build_list_packages", ["name", "project_id"], :name => "index_build_list_packages_on_name_and_project_id"
add_index "build_list_packages", ["platform_id"], :name => "index_build_list_packages_on_platform_id"
add_index "build_list_packages", ["project_id"], :name => "index_build_list_packages_on_project_id"
@@ -131,6 +134,7 @@ ActiveRecord::Schema.define(:version => 20120730214052) do
add_index "build_lists", ["advisory_id"], :name => "index_build_lists_on_advisory_id"
add_index "build_lists", ["arch_id"], :name => "index_build_lists_on_arch_id"
+ add_index "build_lists", ["project_id", "save_to_repository_id", "build_for_platform_id", "arch_id"], :name => "maintainer_search_index"
add_index "build_lists", ["bs_id"], :name => "index_build_lists_on_bs_id", :unique => true
add_index "build_lists", ["project_id"], :name => "index_build_lists_on_project_id"
@@ -332,6 +336,7 @@ ActiveRecord::Schema.define(:version => 20120730214052) do
t.boolean "is_package", :default => true, :null => false
t.integer "average_build_time", :default => 0, :null => false
t.integer "build_count", :default => 0, :null => false
+ t.integer "maintainer_id"
end
add_index "projects", ["owner_id"], :name => "index_projects_on_name_and_owner_id_and_owner_type", :unique => true, :case_sensitive => false
@@ -358,6 +363,7 @@ ActiveRecord::Schema.define(:version => 20120730214052) do
t.datetime "updated_at", :null => false
t.string "interest"
t.text "more"
+ t.string "language"
end
add_index "register_requests", ["email"], :name => "index_register_requests_on_email", :unique => true, :case_sensitive => false
@@ -374,11 +380,12 @@ ActiveRecord::Schema.define(:version => 20120730214052) do
end
create_table "repositories", :force => true do |t|
- t.string "description", :null => false
- t.integer "platform_id", :null => false
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.string "name", :null => false
+ t.string "description", :null => false
+ t.integer "platform_id", :null => false
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ t.string "name", :null => false
+ t.boolean "publish_without_qa", :default => true
end
create_table "settings_notifiers", :force => true do |t|
@@ -393,6 +400,8 @@ ActiveRecord::Schema.define(:version => 20120730214052) do
t.boolean "new_comment_commit_owner", :default => true
t.boolean "new_comment_commit_repo_owner", :default => true
t.boolean "new_comment_commit_commentor", :default => true
+ t.boolean "new_build", :default => true
+ t.boolean "new_associated_build", :default => true
end
create_table "subscribes", :force => true do |t|
diff --git a/lib/plugins/rosa_presenter/base.rb b/lib/plugins/rosa_presenter/base.rb
index eff0f3387..531c74205 100644
--- a/lib/plugins/rosa_presenter/base.rb
+++ b/lib/plugins/rosa_presenter/base.rb
@@ -6,6 +6,7 @@ module RosaPresenter
include ActionDispatch::Routing::UrlFor
include ActionView::Helpers::UrlHelper
include ActionView::Helpers::TextHelper
+ include ActionView::Helpers::JavaScriptHelper
include Rails.application.routes.url_helpers
def initialize(item, opts)
diff --git a/lib/tasks/add_branch.rake b/lib/tasks/add_branch.rake
index 1857cb7c9..47c0bf9ed 100644
--- a/lib/tasks/add_branch.rake
+++ b/lib/tasks/add_branch.rake
@@ -1,22 +1,55 @@
require 'highline/import'
+require 'open-uri'
-desc "Add branch for platform projects"
-task :add_branch => :environment do
- src_branch = ENV['SRC_BRANCH'] || 'import_mandriva2011'
- dst_branch = ENV['DST_BRANCH'] || 'rosa2012lts'
-
- say "START add branch #{dst_branch} from #{src_branch}"
- Platform.find_by_name(dst_branch).repositories.each do |r|
- say "=== Process #{r.name} repo"
- r.projects.find_each do |p|
- next if p.repo.branches.map(&:name).include?(dst_branch)
- say "===== Process #{p.name} project"
- tmp_path = Rails.root.join('tmp', p.name)
- system("git clone #{p.path} #{tmp_path}")
- system("cd #{tmp_path} && git checkout remotes/origin/#{src_branch} || git checkout master")
- system("cd #{tmp_path} && git checkout -b #{dst_branch} && git push origin HEAD")
- FileUtils.rm_rf tmp_path
- end
+namespace :add_branch do
+ desc 'Fork project branch'
+ task :fork_branch, :path, :src_branch, :dst_branch do |t, args|
+ tmp_path = File.join Dir.tmpdir, "#{Time.now.to_i}#{rand(1000)}"
+ system("git clone #{args[:path]} #{tmp_path}")
+ system("cd #{tmp_path} && git push origin :#{args[:dst_branch]}")
+ system("cd #{tmp_path} && git checkout remotes/origin/#{args[:src_branch]} || git checkout master")
+ system("cd #{tmp_path} && git checkout -b #{args[:dst_branch]} && git push origin HEAD")
+ FileUtils.rm_rf tmp_path
+ end
+
+ desc "Add branch for platform projects"
+ task :platform => :environment do
+ src_branch = ENV['SRC_BRANCH'] || 'import_mandriva2011'
+ dst_branch = ENV['DST_BRANCH'] || 'rosa2012lts'
+ say "START add branch #{dst_branch} from #{src_branch}"
+ Platform.find_by_name(dst_branch).repositories.each do |r|
+ say "=== Process #{r.name} repo"
+ r.projects.find_each do |p|
+ next if p.repo.branches.map(&:name).include?(dst_branch)
+ say "===== Process #{p.name} project"
+ Rake::Task['add_branch:fork_branch'].execute(:path => p.path, :src_branch => src_branch, :dst_branch => dst_branch)
+ end
+ end
+ say 'DONE'
+ end
+
+ desc "Add branch for owner projects by list"
+ task :list => :environment do
+ source = ENV['SOURCE'] || 'https://dl.dropbox.com/u/984976/texlive.txt'
+ owner = User.find_by_uname(ENV['OWNER']) || Group.find_by_uname!(ENV['OWNER'] || 'import')
+ platform = Platform.find_by_name!(ENV['PLATFORM'] || 'rosa2012.1')
+ repo = platform.repositories.find_by_name!(ENV['REPO'] || 'main')
+ src_branch = ENV['SRC_BRANCH'] || 'import_cooker'
+ dst_branch = ENV['DST_BRANCH'] || 'rosa2012.1'
+ say "START fork from #{src_branch} to #{dst_branch} branch using #{source} for #{owner.uname}. Add to repo '#{platform.name}/#{repo.name}'."
+ open(source).readlines.each do |name|
+ name.chomp!; name.strip!
+ print "Fork branch for '#{name}'... "
+ if p = Project.find_by_owner_and_name(owner.uname, name)
+ # Rake::Task['add_branch:fork_branch'].execute(:path => p.path, :src_branch => src_branch, :dst_branch => dst_branch)
+ system "bundle exec rake add_branch:fork_branch[#{p.path},#{src_branch},#{dst_branch}] -s RAILS_ENV=#{Rails.env} > /dev/null 2>&1"
+ print 'Ok!'
+ repo.projects << p rescue print ' Add to repo failed!'
+ else
+ print 'Not Found!'
+ end
+ puts
+ end
+ say 'DONE'
end
- say 'DONE'
end
diff --git a/lib/tasks/buildlist.rake b/lib/tasks/buildlist.rake
index c22cea26d..c56ecce00 100644
--- a/lib/tasks/buildlist.rake
+++ b/lib/tasks/buildlist.rake
@@ -1,6 +1,6 @@
namespace :buildlist do
-
+
namespace :clear do
desc 'Remove outdated BuildLists and MassBuilds'
task :outdated => :environment do
@@ -17,4 +17,32 @@ namespace :buildlist do
say "Outdated BuildLists and MassBuilds was successfully removed"
end
end
+
+ namespace :packages do
+ # TODO Maybe do it in migration, because it's just a single query?
+ desc 'Actualize packages for all platforms'
+ task :actualize => :environment do
+
+ say "Updating packages"
+ packages = BuildList::Package.joins( %q{
+ JOIN (
+ SELECT
+ name AS j_pn,
+ package_type AS j_pt,
+ platform_id AS j_plid,
+ MAX(created_at) AS j_ca
+ FROM
+ build_list_packages
+ GROUP BY
+ j_pn, j_pt, j_plid
+ ) AS lastmaints
+ ON
+ j_pn = name
+ AND j_pt = package_type
+ AND j_plid = platform_id
+ AND j_ca = created_at
+ } ).update_all(:actual => true)
+ say "'Actual' setted to #{packages} packages"
+ end
+ end
end
diff --git a/lib/tasks/import.rake b/lib/tasks/import.rake
index 4c5899cbf..d485d14ad 100644
--- a/lib/tasks/import.rake
+++ b/lib/tasks/import.rake
@@ -77,13 +77,15 @@ namespace :import do
namespace :sync do
desc "Sync all repos"
- task :all do
- system("bundle exec rake import:sync:run RELEASE=official/2011 PLATFORM=mandriva2011 REPOSITORY=main")
- system("bundle exec rake import:sync:run RELEASE=official/2011 PLATFORM=mandriva2011 REPOSITORY=contrib")
- system("bundle exec rake import:sync:run RELEASE=official/2011 PLATFORM=mandriva2011 REPOSITORY=non-free")
+ task :all => :environment do
+ # system("bundle exec rake import:sync:run RELEASE=official/2011 PLATFORM=mandriva2011 REPOSITORY=main")
+ # system("bundle exec rake import:sync:run RELEASE=official/2011 PLATFORM=mandriva2011 REPOSITORY=contrib")
+ # system("bundle exec rake import:sync:run RELEASE=official/2011 PLATFORM=mandriva2011 REPOSITORY=non-free")
system("bundle exec rake import:sync:run RELEASE=devel/cooker PLATFORM=cooker REPOSITORY=main")
system("bundle exec rake import:sync:run RELEASE=devel/cooker PLATFORM=cooker REPOSITORY=contrib")
system("bundle exec rake import:sync:run RELEASE=devel/cooker PLATFORM=cooker REPOSITORY=non-free")
+ system("bundle exec rake import:sync:run SOURCE=rsync://mirror.yandex.ru/fedora-epel/6/SRPMS/ DESTINATION=#{File.join(APP_CONFIG['root_path'], 'mirror.yandex.ru', 'fedora-epel', '6', 'SRPMS')} PLATFORM=server_personal REPOSITORY=main OWNER=server BRANCH=import")
+ system("bundle exec rake import:sync:run SOURCE=rsync://rh-mirror.redhat.com/redhat/linux/enterprise/6Server/en/os/SRPMS/ DESTINATION=#{File.join(APP_CONFIG['root_path'], 'rh-mirror.redhat.com', 'redhat', 'linux', 'enterprise', '6Server', 'en', 'os', 'SRPMS')} PLATFORM=server_personal REPOSITORY=main OWNER=server BRANCH=import")
end
task :run => [:rsync, :parse]
@@ -92,7 +94,7 @@ namespace :import do
task :rsync => :environment do
release = ENV['RELEASE'] || 'official/2011'
repository = ENV['REPOSITORY'] || 'main'
- source = "rsync://mirror.yandex.ru/mandriva/#{release}/SRPMS/#{repository}/"
+ source = ENV['SOURCE'] || "rsync://mirror.yandex.ru/mandriva/#{release}/SRPMS/#{repository}/"
destination = ENV['DESTINATION'] || File.join(APP_CONFIG['root_path'], 'mirror.yandex.ru', 'mandriva', release, 'SRPMS', repository)
say "START rsync projects (*.src.rpm) from '#{source}' to '#{destination}' (#{Time.now.utc})"
if system "rsync -rtv --delete --exclude='backports/*' --exclude='testing/*' #{source} #{destination}" # --include='*.src.rpm'
@@ -108,29 +110,34 @@ namespace :import do
release = ENV['RELEASE'] || 'official/2011'
platform = Platform.find_by_name(ENV['PLATFORM'] || "mandriva2011")
repository = platform.repositories.find_by_name(ENV['REPOSITORY'] || 'main')
- source = ENV['SOURCE'] || File.join(APP_CONFIG['root_path'], 'mirror.yandex.ru', 'mandriva', release, 'SRPMS', repository.name)
+ source = ENV['DESTINATION'] || File.join(APP_CONFIG['root_path'], 'mirror.yandex.ru', 'mandriva', release, 'SRPMS', repository.name, '{release,updates}')
owner = Group.find_or_create_by_uname(ENV['OWNER'] || 'import') {|g| g.name = g.uname; g.owner = User.first}
- branch = "import_#{platform.name}"
+ branch = ENV['BRANCH'] || "import_#{platform.name}"
say "START (#{Time.now.utc})"
- Dir[File.join source, '{release,updates}', '*.src.rpm'].each do |srpm_file|
+ Dir[File.join source, '*.src.rpm'].each do |srpm_file|
print "Processing '#{srpm_file}'... "
if name = `rpm -q --qf '[%{Name}]' -p #{srpm_file}` and $?.success? and name.present? and
version = `rpm -q --qf '[%{Version}-%{Release}]' -p #{srpm_file}` and $?.success? and version.present?
project_import = ProjectImport.find_by_name_and_platform_id(name, platform.id) || ProjectImport.by_name(name).where(:platform_id => platform.id).first || ProjectImport.new(:name => name, :platform_id => platform.id)
if version != project_import.version.to_s and File.mtime(srpm_file) > project_import.file_mtime
unless project = project_import.project
- if project = repository.projects.find_by_name(name) || repository.projects.by_name(name).first # fallback to speedup
- print "Found project #{project.name_with_owner} in #{platform.name}/#{repository.name}. "
- elsif scoped = Project.where(:owner_id => owner.id, :owner_type => owner.class) and
- project = scoped.find_by_name(name) || scoped.by_name(name).first
- repository.projects << project
- print "Add project #{project.name_with_owner} to #{platform.name}/#{repository.name}. "
- else
- description = ::Iconv.conv('UTF-8//IGNORE', 'UTF-8', `rpm -q --qf '[%{Description}]' -p #{srpm_file}`)
- project = Project.create!(:name => name, :description => description) {|p| p.owner = owner}
- repository.projects << project
- print "Create project #{project.name_with_owner} at #{platform.name}/#{repository.name}. "
+ if platform.personal? # search project through owner # used for testhat
+ project = Project.find_or_create_by_name_and_owner_type_and_owner_id(name, owner.class.to_s, owner.id)
+ print "Use project #{project.name_with_owner}. "
+ else # search project through repository
+ if project = repository.projects.find_by_name(name) || repository.projects.by_name(name).first # fallback to speedup
+ print "Found project #{project.name_with_owner} in #{platform.name}/#{repository.name}. "
+ elsif scoped = Project.where(:owner_id => owner.id, :owner_type => owner.class) and
+ project = scoped.find_by_name(name) || scoped.by_name(name).first
+ repository.projects << project
+ print "Add project #{project.name_with_owner} to #{platform.name}/#{repository.name}. "
+ else
+ description = ::Iconv.conv('UTF-8//IGNORE', 'UTF-8', `rpm -q --qf '[%{Description}]' -p #{srpm_file}`)
+ project = Project.create!(:name => name, :description => description) {|p| p.owner = owner}
+ repository.projects << project
+ print "Create project #{project.name_with_owner} at #{platform.name}/#{repository.name}. "
+ end
end
end
project.import_srpm(srpm_file, branch)
diff --git a/lib/tasks/projects.rake b/lib/tasks/projects.rake
new file mode 100644
index 000000000..bfe2d982f
--- /dev/null
+++ b/lib/tasks/projects.rake
@@ -0,0 +1,28 @@
+namespace :project do
+
+ namespace :maintainer do
+ desc 'Set maintainer to owner (or to owners owner if owner is a group) to projects'
+ task :set_to_owner => :environment do
+ projects = Project.scoped
+ count = projects.count
+ say "Setting maintainer to all projects (#{count})"
+ percent_per_batch = 100 * 1000 / count
+ i = 1
+
+ projects.find_in_batches do |batch|
+ ActiveRecord::Base.transaction do
+ batch.each do |proj|
+ maintainer_id = (proj.owner_type == 'User') ? proj.owner_id : proj.owner.owner_id
+ proj.maintainer_id = maintainer_id
+ proj.save
+ end
+ end
+ say "#{percent_per_batch * i}% done."
+ i += 1
+ end
+ say "100% done"
+ end
+ end
+ task :maintainer => 'maintainer:set_to_owner'
+
+end
diff --git a/spec/controllers/groups/profile_controller_spec.rb b/spec/controllers/groups/profile_controller_spec.rb
index a0e29c31b..8ea65d72b 100644
--- a/spec/controllers/groups/profile_controller_spec.rb
+++ b/spec/controllers/groups/profile_controller_spec.rb
@@ -129,7 +129,8 @@ describe Groups::ProfileController do
before(:each) do
@user = FactoryGirl.create(:user)
set_session_for(@user)
- @group.update_attribute(:owner, @user)
+ @group.owner = @user
+ @group.save
@group.actors.create(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
end
diff --git a/spec/controllers/platforms/key_pairs_controller_spec.rb b/spec/controllers/platforms/key_pairs_controller_spec.rb
index 5b27e41b0..e9b73fc97 100644
--- a/spec/controllers/platforms/key_pairs_controller_spec.rb
+++ b/spec/controllers/platforms/key_pairs_controller_spec.rb
@@ -126,7 +126,9 @@ describe Platforms::KeyPairsController do
before(:each) do
@user = FactoryGirl.create(:user)
set_session_for(@user)
- @platform.update_attribute(:owner, @user)
+
+ @platform.owner = @user
+ @platform.save
end
it_should_behave_like 'key_pair platform owner'
diff --git a/spec/controllers/platforms/maintainers_controller_spec.rb b/spec/controllers/platforms/maintainers_controller_spec.rb
new file mode 100644
index 000000000..d4c03b245
--- /dev/null
+++ b/spec/controllers/platforms/maintainers_controller_spec.rb
@@ -0,0 +1,69 @@
+# -*- encoding : utf-8 -*-
+require 'spec_helper'
+
+shared_examples_for 'guest user' do
+
+ it "should be able to view maintainers list(index)" do
+ get :index, :platform_id => @platform.id
+ response.should be_success
+ end
+end
+
+describe Platforms::MaintainersController do
+ before(:each) do
+ stub_symlink_methods
+
+ @platform = FactoryGirl.create(:platform)
+ @user = FactoryGirl.create(:user)
+ set_session_for(@user)
+ end
+
+ context 'for guest' do
+ before {set_session_for(User.new)}
+
+ it "should be able to view maintainers list(index)", :anonymous_access => true do
+ get :index, :platform_id => @platform.id
+ response.should be_success
+ end
+
+ it "should not be able to view maintainers list(index)", :anonymous_access => false do
+ get :index, :platform_id => @platform.id
+ response.should redirect_to(new_user_session_path)
+ end
+ end
+
+ context 'for global admin' do
+ before(:each) do
+ @user.role = "admin"
+ @user.save
+ end
+
+ it_should_behave_like 'guest user'
+ end
+
+ context 'for registrated user' do
+
+ it_should_behave_like 'guest user'
+ end
+
+
+ context 'for platform owner' do
+ before(:each) do
+ @user = @platform.owner
+ set_session_for(@user)
+ end
+
+ it_should_behave_like 'guest user'
+ end
+
+ context 'for platform member' do
+ before(:each) do
+ @platform.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
+ end
+
+ it_should_behave_like 'guest user'
+ end
+
+end
+
+
diff --git a/spec/controllers/platforms/mass_builds_controller_spec.rb b/spec/controllers/platforms/mass_builds_controller_spec.rb
index 1cd611d72..8c673fb99 100644
--- a/spec/controllers/platforms/mass_builds_controller_spec.rb
+++ b/spec/controllers/platforms/mass_builds_controller_spec.rb
@@ -23,7 +23,7 @@ shared_examples_for 'mass_build platform owner' do
end
it 'should not be able to perform cancel action if stop_build is true' do
- @mass_build.update_attribute(:stop_build, true)
+ @mass_build.stop_build = true; @mass_build.save
post :cancel, :platform_id => @platform, :id => @mass_build
response.should redirect_to(forbidden_path)
end
@@ -133,7 +133,9 @@ describe Platforms::MassBuildsController do
before(:each) do
@user = FactoryGirl.create(:user)
set_session_for(@user)
- @platform.update_attribute(:owner, @user)
+
+ @platform.owner = @user
+ @platform.save
end
it_should_behave_like 'mass_build platform owner'
diff --git a/spec/controllers/platforms/platforms_controller_spec.rb b/spec/controllers/platforms/platforms_controller_spec.rb
index 242315f10..6ec4157b4 100644
--- a/spec/controllers/platforms/platforms_controller_spec.rb
+++ b/spec/controllers/platforms/platforms_controller_spec.rb
@@ -2,7 +2,6 @@
require 'spec_helper'
shared_examples_for 'platform owner' do
- it_should_behave_like 'platform index viewer'
it 'should not be able to destroy personal platform' do
delete :destroy, :id => @personal_platform.id
@@ -19,14 +18,39 @@ shared_examples_for 'platform owner' do
end
end
-shared_examples_for 'platform index viewer' do
+shared_examples_for 'system registered user' do
it 'should be able to perform index action' do
get :index
response.should render_template(:index)
end
-end
+ it 'should be able to perform show action' do
+ get :show, :id => @platform.id
+ response.should render_template(:show)
+ assigns(:platform).should eq @platform
+ end
+
+ it 'should be able to perform members action' do
+ get :members, :id => @platform.id
+ response.should render_template(:members)
+ response.should be_success
+ end
+
+ it 'should be able to perform advisories action' do
+ get :advisories, :id => @platform.id
+ response.should render_template(:advisories)
+ response.should be_success
+ end
+
+end
+
shared_examples_for 'user without create rights' do
+
+ it 'should not be able to perform new action' do
+ get :new
+ response.should redirect_to(forbidden_path)
+ end
+
it 'should not be able to create platform' do
post :create, @create_params
response.should redirect_to(forbidden_path)
@@ -39,16 +63,22 @@ describe Platforms::PlatformsController do
@platform = FactoryGirl.create(:platform)
@personal_platform = FactoryGirl.create(:platform, :platform_type => 'personal')
+
@user = FactoryGirl.create(:user)
+ set_session_for(@user)
+
@create_params = {:platform => {
:name => 'pl1',
:description => 'pl1',
:platform_type => 'main',
:distrib_type => APP_CONFIG['distr_types'].first
}}
- end
+ end
context 'for guest' do
+ before(:each) do
+ set_session_for(User.new)
+ end
[:index, :create].each do |action|
it "should not be able to perform #{ action } action" do
@@ -57,21 +87,39 @@ describe Platforms::PlatformsController do
end
end
- [:show, :new, :edit, :clone, :destroy].each do |action|
+ [:new, :edit, :clone, :destroy].each do |action|
it "should not be able to perform #{ action } action" do
get action, :id => @platform
response.should redirect_to(new_user_session_path)
end
end
+
+ [:show, :members, :advisories].each do |action|
+ it "should not be able to perform #{ action } action", :anonymous_access => false do
+ get action, :id => @platform
+ response.should redirect_to(new_user_session_path)
+ end
+ end
+
+ [:show, :members, :advisories].each do |action|
+ it "should be able to perform #{ action } action", :anonymous_access => true do
+ get action, :id => @platform
+ response.should render_template(action)
+ response.should be_success
+ end
+ end
+
end
context 'for global admin' do
before(:each) do
- @admin = FactoryGirl.create(:admin)
- @user = FactoryGirl.create(:user)
- set_session_for(@admin)
+ @user.role = "admin"
+ @user.save
end
+ it_should_behave_like 'system registered user'
+ it_should_behave_like 'platform owner'
+
it 'should be able to perform new action' do
get :new
response.should render_template(:new)
@@ -86,51 +134,37 @@ describe Platforms::PlatformsController do
lambda { post :create, @create_params }.should change{ Platform.count }.by(1)
end
- it_should_behave_like 'platform owner'
-
it 'should create platform with mentioned owner if owner id present' do
- post :create, @create_params.merge({:admin_id => @user.id, :admin_uname => @user.uname})
- Platform.last.owner.id.should eql(@user.id)
+ owner = FactoryGirl.create(:user)
+ post :create, @create_params.merge({:admin_id => owner.id, :admin_uname => owner.uname})
+ Platform.last.owner.id.should eql(owner.id)
end
it 'should create platform with current user as owner if owner id not present' do
post :create, @create_params
- Platform.last.owner.id.should eql(@admin.id)
+ Platform.last.owner.id.should eql(@user.id)
end
end
context 'for owner user' do
before(:each) do
- @user = FactoryGirl.create(:user)
+ @user = @platform.owner
set_session_for(@user)
- @platform.update_attribute(:owner, @user)
- @platform.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
end
+ it_should_behave_like 'system registered user'
it_should_behave_like 'user without create rights'
it_should_behave_like 'platform owner'
- it 'should be able to perform new action' do
- get :new
- response.should redirect_to(forbidden_path)
- end
-
- it 'should be able to perform create action' do
- post :create, @create_params
- response.should redirect_to(forbidden_path)
- end
-
end
context 'for reader user' do
before(:each) do
- @user = FactoryGirl.create(:user)
- set_session_for(@user)
@platform.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'reader')
end
- it_should_behave_like 'platform index viewer'
+ it_should_behave_like 'system registered user'
it_should_behave_like 'user without create rights'
it 'should not be able to perform destroy action' do
diff --git a/spec/controllers/platforms/products_controller_spec.rb b/spec/controllers/platforms/products_controller_spec.rb
index e90d48cbc..4c500eb48 100644
--- a/spec/controllers/platforms/products_controller_spec.rb
+++ b/spec/controllers/platforms/products_controller_spec.rb
@@ -31,9 +31,16 @@ describe Platforms::ProductsController do
@product = FactoryGirl.create(:product, :platform => @platform)
@create_params = {:product => {:name => 'pro'}, :platform_id => @platform.id}
@update_params = {:product => {:name => 'pro2'}, :platform_id => @platform.id}
+
+ @user = FactoryGirl.create(:user)
+ set_session_for(@user)
end
- context 'for guest' do
+ context 'for guest' do
+ before(:each) do
+ set_session_for(User.new)
+ end
+
[:create].each do |action|
it "should not be able to perform #{ action } action" do
get action, :platform_id => @platform.id
@@ -41,40 +48,56 @@ describe Platforms::ProductsController do
end
end
- [:show, :new, :edit, :update, :destroy].each do |action|
+ [:new, :edit, :update, :destroy].each do |action|
it "should not be able to perform #{ action } action" do
get action, :id => @product.id, :platform_id => @platform.id
response.should redirect_to(new_user_session_path)
end
end
+
+ [:show, :index].each do |action|
+ it "should not be able to perform #{ action } action", :anonymous_access => false do
+ get action, :id => @product.id, :platform_id => @platform.id
+ response.should redirect_to(new_user_session_path)
+ end
+ end
+
+ [:show, :index].each do |action|
+ it "should be able to perform #{ action } action", :anonymous_access => true do
+ get action, :id => @product.id, :platform_id => @platform.id
+ response.should render_template(action)
+ response.should be_success
+ end
+ end
end
context 'for global admin' do
- before(:each) do
- @admin = FactoryGirl.create(:admin)
- set_session_for(@admin)
- end
+ before(:each) do
+ @user.role = "admin"
+ @user.save
+ end
it_should_behave_like 'admin user'
end
-
+ context 'for platform owner' do
+ before(:each) do
+ @user = @platform.owner
+ set_session_for(@user)
+ end
+
+ it_should_behave_like 'admin user'
+ end
context 'for admin relation user' do
- before(:each) do
- @user = FactoryGirl.create(:user)
- set_session_for(@user)
+ before(:each) do
@platform.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
- end
+ end
it_should_behave_like 'admin user'
end
context 'for no relation user' do
- before(:each) do
- @user = FactoryGirl.create(:user)
- set_session_for(@user)
- end
it 'should not be able to create product' do
lambda { post :create, @create_params }.should change{ Product.count }.by(0)
diff --git a/spec/controllers/platforms/repositories_controller_spec.rb b/spec/controllers/platforms/repositories_controller_spec.rb
index 82c4a5712..c4481c9ea 100644
--- a/spec/controllers/platforms/repositories_controller_spec.rb
+++ b/spec/controllers/platforms/repositories_controller_spec.rb
@@ -5,29 +5,97 @@ shared_examples_for 'not destroy personal repository' do
it 'should not be able to destroy personal repository' do
lambda { delete :destroy, :id => @personal_repository.id, :platform_id =>
@personal_repository.platform.id}.should change{ Repository.count }.by(0)
- response.should redirect_to(forbidden_path)
+ response.should redirect_to(redirect_path)
end
end
shared_examples_for 'user with change projects in repository rights' do
-
+
it 'should be able to see add_project page' do
get :add_project, :id => @repository.id, :platform_id => @platform.id
response.should render_template(:projects_list)
end
-
+
it 'should be able to add project to repository' do
get :add_project, :id => @repository.id, :platform_id => @platform.id, :project_id => @project.id
response.should redirect_to(platform_repository_path(@repository.platform, @repository))
- @repository.projects.should include (@project)
+ @repository.projects.should include(@project)
end
-
+
it 'should be able to remove project from repository' do
get :remove_project, :id => @repository.id, :platform_id => @platform.id, :project_id => @project.id
response.should redirect_to(platform_repository_path(@repository.platform, @repository))
- @repository.projects.should_not include (@project)
+ @repository.projects.should_not include(@project)
end
-
+
+end
+
+shared_examples_for 'user without change projects in repository rights' do
+ it 'should not be able to add project to repository' do
+ get :add_project, :id => @repository.id, :platform_id => @platform.id, :project_id => @project.id
+ response.should redirect_to(redirect_path)
+ @repository.projects.should_not include(@project)
+ end
+
+ it 'should not be able to remove project from repository' do
+ delete :remove_project, :id => @repository.id, :platform_id => @platform.id, :project_id => @project.id
+ response.should redirect_to(redirect_path)
+ @repository.projects.should_not include(@project)
+ end
+end
+
+shared_examples_for 'registered user or guest' do
+ it 'should not be able to perform new action' do
+ get :new, :platform_id => @platform.id
+ response.should redirect_to(redirect_path)
+ end
+
+ it 'should not be able to perform create action' do
+ post :create, @create_params
+ lambda { post :create, @create_params }.should change{ Repository.count }.by(0)
+ response.should redirect_to(redirect_path)
+ end
+
+ it 'should not be able to perform edit action' do
+ get :edit, :id => @repository.id, :platform_id => @platform.id
+ response.should redirect_to(redirect_path)
+ end
+
+ it 'should not be able to perform update action' do
+ put :update, :id => @repository.id, :platform_id => @platform.id
+ response.should redirect_to(redirect_path)
+ end
+
+ it 'should not be able to add new member to repository' do
+ post :add_member, :id => @repository.id, :platform_id => @platform.id, :member_id => @another_user.id
+ response.should redirect_to(redirect_path)
+ @repository.members.should_not include(@another_user)
+ end
+
+ it 'should not be able to remove member from repository' do
+ @repository.relations.create(:role => 'admin', :actor => @another_user)
+ delete :remove_member, :id => @repository.id, :platform_id => @platform.id, :member_id => @another_user.id
+ response.should redirect_to(redirect_path)
+ @repository.members.should include(@another_user)
+ end
+
+ it 'should not be able to remove members from repository' do
+ another_user2 = FactoryGirl.create(:user)
+ @repository.relations.create(:role => 'admin', :actor => @another_user)
+ @repository.relations.create(:role => 'admin', :actor => another_user2)
+ post :remove_members, :id => @repository.id, :platform_id => @platform.id,
+ :user_remove => {@another_user.id => [1], another_user2.id => [1]}
+ response.should redirect_to(redirect_path)
+ @repository.members.should include(@another_user, another_user2)
+ end
+
+ it 'should not be able to destroy repository in main platform' do
+ delete :destroy, :id => @repository.id
+ response.should redirect_to(redirect_path)
+ lambda { delete :destroy, :id => @repository.id }.should_not change{ Repository.count }.by(-1)
+ end
+
+ it_should_behave_like 'not destroy personal repository'
end
shared_examples_for 'registered user' do
@@ -40,6 +108,12 @@ shared_examples_for 'registered user' do
get :show, :id => @repository.id
response.should render_template(:show)
end
+
+ it 'should be able to perform projects_list action' do
+ get :projects_list, :id => @repository.id, :platform_id => @platform.id, :format => :json
+ response.should be_success
+ end
+
end
shared_examples_for 'platform admin user' do
@@ -61,8 +135,38 @@ shared_examples_for 'platform admin user' do
response.should redirect_to(platform_repositories_path(@repository.platform))
end
+ it 'should be able to perform edit action' do
+ get :edit, :id => @repository.id, :platform_id => @platform.id
+ response.should render_template(:edit)
+ end
+
+ it 'should be able to add new member to repository' do
+ post :add_member, :id => @repository.id, :platform_id => @platform.id, :member_id => @another_user.id
+ response.should redirect_to(edit_platform_repository_path(@repository.platform, @repository))
+ @repository.members.should include(@another_user)
+ end
+
+ it 'should be able to remove member from repository' do
+ @repository.relations.create(:role => 'admin', :actor => @another_user)
+ delete :remove_member, :id => @repository.id, :platform_id => @platform.id, :member_id => @another_user.id
+ response.should redirect_to(edit_platform_repository_path(@repository.platform, @repository))
+ @repository.members.should_not include(@another_user)
+ end
+
+ it 'should be able to remove members from repository' do
+ another_user2 = FactoryGirl.create(:user)
+ @repository.relations.create(:role => 'admin', :actor => @another_user)
+ @repository.relations.create(:role => 'admin', :actor => another_user2)
+ post :remove_members, :id => @repository.id, :platform_id => @platform.id,
+ :user_remove => {@another_user.id => [1], another_user2.id => [1]}
+ response.should redirect_to(edit_platform_repository_path(@repository.platform, @repository))
+ @repository.members.should_not include(@another_user, another_user2)
+ end
+
it_should_behave_like 'user with change projects in repository rights'
- it_should_behave_like 'not destroy personal repository'
+ it_should_behave_like 'not destroy personal repository' do
+ let(:redirect_path) { forbidden_path }
+ end
end
describe Platforms::RepositoriesController do
@@ -75,83 +179,85 @@ describe Platforms::RepositoriesController do
@project = FactoryGirl.create(:project)
@another_user = FactoryGirl.create(:user)
@create_params = {:repository => {:name => 'pro', :description => 'pro2'}, :platform_id => @platform.id}
+
+ @user = FactoryGirl.create(:user)
+ set_session_for(@user)
end
context 'for guest' do
- [:index, :create].each do |action|
- it "should not be able to perform #{ action } action" do
- get action, :platform_id => @platform
- response.should redirect_to(new_user_session_path)
- end
+
+ before(:each) do
+ set_session_for(User.new)
end
- [:show, :new, :add_project, :remove_project, :destroy].each do |action|
- it "should not be able to perform #{ action } action" do
- get action, :id => @repository.id
- response.should redirect_to(new_user_session_path)
- end
+ it_should_behave_like 'registered user' if APP_CONFIG['anonymous_access']
+
+ let(:redirect_path) { new_user_session_path }
+ it_should_behave_like 'registered user or guest'
+ it_should_behave_like 'user without change projects in repository rights'
+
+ it "should not be able to perform show action", :anonymous_access => false do
+ get :show, :id => @repository
+ response.should redirect_to(new_user_session_path)
end
+
+ it "should not be able to perform index action", :anonymous_access => false do
+ get :index, :platform_id => @platform
+ response.should redirect_to(new_user_session_path)
+ end
+
+ it 'should not be able to perform projects_list action', :anonymous_access => false do
+ get :projects_list, :id => @repository.id, :platform_id => @platform.id, :format => :json
+ response.response_code.should == 401
+ end
+
+ end
+
+ context 'for user' do
+ it_should_behave_like 'registered user'
+
+ let(:redirect_path) { forbidden_path }
+ it_should_behave_like 'registered user or guest'
+ it_should_behave_like 'user without change projects in repository rights'
end
context 'for admin' do
before(:each) do
- @admin = FactoryGirl.create(:admin)
- set_session_for(@admin)
+ @user.role = "admin"
+ @user.save
end
it_should_behave_like 'platform admin user'
end
-
+
context 'for platform owner user' do
before(:each) do
- @user = FactoryGirl.create(:user)
+ @user = @repository.platform.owner
set_session_for(@user)
- @repository.platform.update_attribute(:owner, @user)
- @repository.platform.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
end
it_should_behave_like 'platform admin user'
end
- context 'for user' do
+ context 'for platform member user' do
before(:each) do
- @user = FactoryGirl.create(:user)
- set_session_for(@user)
+ @platform.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
end
-
+
+ it_should_behave_like 'platform admin user'
+ end
+
+ context 'for repository member user' do
+ before(:each) do
+ @repository.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
+ end
+
it_should_behave_like 'registered user'
- it 'should not be able to perform new action' do
- get :new, :platform_id => @platform.id
- response.should redirect_to(forbidden_path)
- end
-
- it 'should not be able to perform create action' do
- post :create, @create_params
- lambda { post :create, @create_params }.should change{ Repository.count }.by(0)
- response.should redirect_to(forbidden_path)
- end
-
- it 'should not be able to destroy repository in main platform' do
- delete :destroy, :id => @repository.id
- response.should redirect_to(forbidden_path)
- lambda { delete :destroy, :id => @repository.id }.should_not change{ Repository.count }.by(-1)
- end
-
- it 'should not be able to add project to repository' do
- get :add_project, :id => @repository.id, :platform_id => @platform.id, :project_id => @project.id
- response.should redirect_to(forbidden_path)
- @repository.projects.should_not include (@project)
- end
-
- it 'should not be able to remove project from repository' do
- get :remove_project, :id => @repository.id, :platform_id => @platform.id, :project_id => @project.id
- response.should redirect_to(forbidden_path)
- @repository.projects.should_not include (@project)
- end
-
- it_should_behave_like 'not destroy personal repository'
+ let(:redirect_path) { forbidden_path }
+ it_should_behave_like 'registered user or guest'
+ it_should_behave_like 'user with change projects in repository rights'
end
end
diff --git a/spec/controllers/projects/build_lists_controller_spec.rb b/spec/controllers/projects/build_lists_controller_spec.rb
index b2aa0d17d..4e9575f9c 100644
--- a/spec/controllers/projects/build_lists_controller_spec.rb
+++ b/spec/controllers/projects/build_lists_controller_spec.rb
@@ -109,7 +109,7 @@ describe Projects::BuildListsController do
set_session_for(@user)
@show_params = {:owner_name => @project.owner.uname, :project_name => @project.name, :id => @build_list.id}
end
-
+
context 'for all build lists' do
before(:each) do
@build_list1 = FactoryGirl.create(:build_list_core)
@@ -326,8 +326,8 @@ describe Projects::BuildListsController do
describe 'publish_build' do
before {
test_git_commit(build_list.project)
- build_list.update_attribute :commit_hash, build_list.project.repo.commits('master').last.id
- build_list.update_attribute(:status, BuildList::BUILD_PUBLISH)
+ build_list.update_column(:commit_hash, build_list.project.repo.commits('master').last.id)
+ build_list.update_column(:status, BuildList::BUILD_PUBLISH)
build_list_package
}
@@ -337,7 +337,7 @@ describe Projects::BuildListsController do
end
it(:passes) {
- build_list.update_attribute(:status, BuildServer::BUILD_STARTED)
+ build_list.update_column(:status, BuildServer::BUILD_STARTED)
do_get(BuildServer::SUCCESS)
response.should be_ok
}
@@ -401,7 +401,7 @@ describe Projects::BuildListsController do
describe 'pre_build' do
before do
- build_list.update_attribute :status, BuildList::BUILD_PENDING
+ build_list.update_column :status, BuildList::BUILD_PENDING
end
def do_get
@@ -428,29 +428,29 @@ describe Projects::BuildListsController do
context 'with auto_publish' do
it(:passes) {
- build_list.update_attribute(:started_at, (Time.now - 1.day))
- build_list.update_attribute(:status, BuildServer::BUILD_STARTED)
+ build_list.update_column(:started_at, (Time.now - 1.day))
+ build_list.update_column(:status, BuildServer::BUILD_STARTED)
build_list.reload
lambda{ do_get(BuildServer::SUCCESS) }.should change(build_list, :status).to(BuildList::BUILD_PUBLISH)
}
it(:passes) {
- build_list.update_attribute(:started_at, (Time.now - 1.day))
- build_list.update_attribute(:status, BuildServer::BUILD_STARTED)
+ build_list.update_column(:started_at, (Time.now - 1.day))
+ build_list.update_column(:status, BuildServer::BUILD_STARTED)
lambda{ do_get(BuildServer::BUILD_ERROR) }.should change(build_list, :status).to(BuildServer::BUILD_ERROR)
}
end
context 'without auto_publish' do
- before { build_list.update_attribute(:auto_publish, false) }
+ before { build_list.update_column(:auto_publish, false) }
it(:passes) {
- build_list.update_attribute(:started_at, (Time.now - 1.day))
- build_list.update_attribute(:status, BuildServer::BUILD_STARTED)
+ build_list.update_column(:started_at, (Time.now - 1.day))
+ build_list.update_column(:status, BuildServer::BUILD_STARTED)
lambda{ do_get(BuildServer::SUCCESS) }.should change(build_list, :status).to(BuildServer::SUCCESS)
}
it(:passes) {
- build_list.update_attribute(:started_at, (Time.now - 1.day))
- build_list.update_attribute(:status, BuildServer::BUILD_STARTED)
+ build_list.update_column(:started_at, (Time.now - 1.day))
+ build_list.update_column(:status, BuildServer::BUILD_STARTED)
lambda{ do_get(BuildServer::BUILD_ERROR) }.should change(build_list, :status).to(BuildServer::BUILD_ERROR)
}
end
diff --git a/spec/controllers/projects/collaborators_controller_spec.rb b/spec/controllers/projects/collaborators_controller_spec.rb
index 5c8d320c2..eac133b35 100644
--- a/spec/controllers/projects/collaborators_controller_spec.rb
+++ b/spec/controllers/projects/collaborators_controller_spec.rb
@@ -1,21 +1,35 @@
# -*- encoding : utf-8 -*-
require 'spec_helper'
-def create_params
- @user_params = {
- :actor_id => @another_user.id.to_s,
- :actor_type => 'user',
- :role => 'reader'
- }
- @group_params = {
- :actor_id => @group.id.to_s,
- :actor_type => 'group',
- :role => 'reader'
- }
- @create_params = {
- :owner_name => @project.owner.uname, :project_name => @project.name,
- :format => :json
- }
+shared_context "collaborators controller" do
+ before(:each) do
+ stub_symlink_methods
+ @project = FactoryGirl.create(:project)
+ @another_user = FactoryGirl.create(:user)
+ @group = FactoryGirl.create(:group)
+ @member_user = FactoryGirl.create(:user)
+ # Create relation with 'writer' rights
+ @collaborator = Collaborator.create(:actor => @member_user, :project => @project, :role => 'writer')
+
+ @user = FactoryGirl.create(:user)
+ set_session_for(@user)
+
+ @user_params = {
+ :actor_id => @another_user.id.to_s,
+ :actor_type => 'user',
+ :role => 'reader'
+ }
+ @group_params = {
+ :actor_id => @group.id.to_s,
+ :actor_type => 'group',
+ :role => 'reader'
+ } if @group
+ @create_params = {
+ :owner_name => @project.owner.uname, :project_name => @project.name,
+ :format => :json
+ }
+ @update_params = @create_params.merge(:collaborator => {:role => 'reader'})
+ end
end
shared_examples_for 'project admin user' do
@@ -25,7 +39,7 @@ shared_examples_for 'project admin user' do
end
it 'should be able to perform update action' do
- put :update, {:owner_name => @project.owner.uname, :project_name => @project.name, :id => @collaborator.id}.merge(@update_params)
+ put :update, {:id => @collaborator.id}.merge(@update_params)
response.should be_success
end
@@ -40,7 +54,7 @@ shared_examples_for 'project admin user' do
end
it 'should be able to set reader role for any user' do
- put :update, {:owner_name => @project.owner.uname, :project_name => @project.name, :id => @collaborator.id}.merge(@update_params)
+ put :update, {:id => @collaborator.id}.merge(@update_params)
@another_user.relations.exists? :target_id => @project.id, :target_type => 'Project', :role => 'read'
end
end
@@ -52,45 +66,38 @@ shared_examples_for 'user with no rights for this project' do
end
it 'should not be able to perform update action' do
- put :update, {:owner_name => @project.owner.uname, :project_name => @project.name, :id => @collaborator.id}.merge(@update_params)
+ put :update, {:id => @collaborator.id}.merge(@update_params)
response.should redirect_to(forbidden_path)
end
it 'should not be able to set reader role for any user' do
- put :update, {:owner_name => @project.owner.uname, :project_name => @project.name, :id => @collaborator.id}.merge(@update_params)
+ put :update, {:id => @collaborator.id}.merge(@update_params)
!@another_user.relations.exists? :target_id => @project.id, :target_type => 'Project', :role => 'read'
end
end
describe Projects::CollaboratorsController do
- before(:each) do
- stub_symlink_methods
- @project = FactoryGirl.create(:project)
- @another_user = FactoryGirl.create(:user)
- @member_user = FactoryGirl.create(:user)
- @update_params = {:collaborator => {:role => :reader}, :format => :json}
- # Create relation with 'writer' rights
- @collaborator = Collaborator.create(:actor => @member_user, :project => @project, :role => 'writer')
- end
+ include_context "collaborators controller"
context 'for guest' do
+ before(:each) do
+ set_session_for(User.new)
+ end
it 'should not be able to perform index action' do
get :index, :owner_name => @project.owner.uname, :project_name => @project.name
response.should redirect_to(new_user_session_path)
end
it 'should not be able to perform update action' do
- put :update, {:owner_name => @project.owner.uname, :project_name => @project.name, :id => @collaborator.id}.merge(@update_params)
+ put :update, {:id => @collaborator.id}.merge(@update_params)
response.code.should == '401'
end
end
context 'for global admin' do
before(:each) do
- @admin = FactoryGirl.create(:admin)
- set_session_for(@admin)
- @group = FactoryGirl.create(:group)
- create_params
+ @user.role = "admin"
+ @user.save
end
it_should_behave_like 'project admin user'
@@ -98,28 +105,16 @@ describe Projects::CollaboratorsController do
context 'for admin user' do
before(:each) do
- @user = FactoryGirl.create(:user)
-# @user.relations
- set_session_for(@user)
- @group = FactoryGirl.create(:group)
@project.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
- create_params
end
it_should_behave_like 'project admin user'
-
end
context 'for owner user' do
before(:each) do
- @user = FactoryGirl.create(:user)
+ @user = @project.owner # owner should be user
set_session_for(@user)
- @group = FactoryGirl.create(:group)
-
- @project.update_attribute(:owner, @user)
- @project.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
-
- create_params
end
it_should_behave_like 'project admin user'
@@ -127,8 +122,6 @@ describe Projects::CollaboratorsController do
context 'for reader user' do
before(:each) do
- @user = FactoryGirl.create(:user)
- set_session_for(@user)
@project.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'reader')
end
@@ -137,8 +130,6 @@ describe Projects::CollaboratorsController do
context 'for writer user' do
before(:each) do
- @user = FactoryGirl.create(:user)
- set_session_for(@user)
@project.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'writer')
end
diff --git a/spec/controllers/projects/comments_controller_spec.rb b/spec/controllers/projects/comments_controller_spec.rb
index 1e0501495..3fb36a7cd 100644
--- a/spec/controllers/projects/comments_controller_spec.rb
+++ b/spec/controllers/projects/comments_controller_spec.rb
@@ -1,13 +1,33 @@
# -*- encoding : utf-8 -*-
require 'spec_helper'
+shared_context "comments controller" do
+ before(:each) do
+ stub_symlink_methods
+
+ @project = FactoryGirl.create(:project)
+ @issue = FactoryGirl.create(:issue, :project_id => @project.id, :user => FactoryGirl.create(:user))
+ @comment = FactoryGirl.create(:comment, :commentable => @issue, :project_id => @project.id)
+
+ @user = FactoryGirl.create(:user)
+ @own_comment = FactoryGirl.create(:comment, :commentable => @issue, :user => @user, :project_id => @project.id)
+
+ set_session_for(@user)
+
+ @address = {:owner_name => @project.owner.uname, :project_name => @project.name, :issue_id => @issue.serial_id}
+ @create_params = {:comment => {:body => 'I am a comment!'}}.merge(@address)
+ @update_params = {:comment => {:body => 'updated'}}.merge(@address)
+ end
+
+end
+
shared_examples_for 'user with create comment rights' do
it 'should be able to perform create action' do
post :create, @create_params
response.should redirect_to(project_issue_path(@project, @issue))
end
- it 'should create subscribe object into db' do
+ it 'should create comment in the database' do
lambda{ post :create, @create_params }.should change{ Comment.count }.by(1)
end
end
@@ -18,7 +38,7 @@ shared_examples_for 'user with update own comment rights' do
response.should redirect_to([@project, @issue])
end
- it 'should update subscribe body' do
+ it 'should update comment body' do
put :update, {:id => @own_comment.id}.merge(@update_params)
@own_comment.reload.body.should == 'updated'
end
@@ -30,7 +50,7 @@ shared_examples_for 'user with update stranger comment rights' do
response.should redirect_to([@project, @issue])
end
- it 'should update issue title' do
+ it 'should update comment body' do
put :update, {:id => @comment.id}.merge(@update_params)
@comment.reload.body.should == 'updated'
end
@@ -42,7 +62,7 @@ shared_examples_for 'user without update stranger comment rights' do
response.should redirect_to(forbidden_path)
end
- it 'should not update issue title' do
+ it 'should not update comment body' do
put :update, {:id => @comment.id}.merge(@update_params)
@comment.reload.body.should_not == 'updated'
end
@@ -50,42 +70,39 @@ end
shared_examples_for 'user without destroy comment rights' do
it 'should not be able to perform destroy action' do
- delete :destroy, :id => @comment.id, :issue_id => @issue.serial_id, :owner_name => @project.owner.uname, :project_name => @project.name
+ delete :destroy, {:id => @comment.id}.merge(@address)
response.should redirect_to(forbidden_path)
end
- it 'should not reduce comments count' do
- lambda{ delete :destroy, :id => @comment.id, :issue_id => @issue.serial_id, :owner_name => @project.owner.uname, :project_name => @project.name }.should change{ Issue.count }.by(0)
+ it 'should not delete comment from database' do
+ lambda{ delete :destroy, {:id => @comment.id}.merge(@address)}.should change{ Issue.count }.by(0)
end
end
-#shared_examples_for 'user with destroy rights' do
-# it 'should be able to perform destroy action' do
-# delete :destroy, :id => @comment.id, :issue_id => @issue.id, :owner_name => @project.owner.uname, :project_name => @project.name
-# response.should redirect_to([@project, @issue])
-# end
-#
-# it 'should reduce comments count' do
-# lambda{ delete :destroy, :id => @comment.id, :issue_id => @issue.id, :owner_name => @project.owner.uname, :project_name => @project.name }.should change{ Comment.count }.by(-1)
-# end
-#end
+shared_examples_for 'user with destroy comment rights' do
+ it 'should be able to perform destroy action' do
+ delete :destroy, {:id => @comment.id}.merge(@address)
+ response.should redirect_to([@project, @issue])
+ end
+
+ it 'should delete comment from database' do
+ lambda{ delete :destroy, {:id => @comment.id}.merge(@address)}.should change{ Comment.count }.by(-1)
+ end
+end
describe Projects::CommentsController do
- before(:each) do
- stub_symlink_methods
+ include_context "comments controller"
- @project = FactoryGirl.create(:project)
- @issue = FactoryGirl.create(:issue, :project_id => @project.id, :user => FactoryGirl.create(:user))
- @comment = FactoryGirl.create(:comment, :commentable => @issue, :project_id => @project.id)
+ context 'for global admin user' do
+ before(:each) do
+ @user.role = "admin"
+ @user.save
+ end
- @create_params = {:comment => {:body => 'I am a comment!'}, :owner_name => @project.owner.uname, :project_name => @project.name, :issue_id => @issue.serial_id}
- @update_params = {:comment => {:body => 'updated'}, :owner_name => @project.owner.uname, :project_name => @project.name, :issue_id => @issue.serial_id}
-
- any_instance_of(Project, :versions => ['v1.0', 'v2.0'])
-
- @user = FactoryGirl.create(:user)
- set_session_for(@user)
- @own_comment = FactoryGirl.create(:comment, :commentable => @issue, :user => @user, :project_id => @project.id)
+ it_should_behave_like 'user with create comment rights'
+ it_should_behave_like 'user with update stranger comment rights'
+ it_should_behave_like 'user with update own comment rights'
+ it_should_behave_like 'user with destroy comment rights'
end
context 'for project admin user' do
@@ -101,10 +118,7 @@ describe Projects::CommentsController do
context 'for project owner user' do
before(:each) do
- @project.update_attribute(:owner, @user)
- @project.relations.destroy_all
- @project.relations.create :actor_id => @project.owner.id, :actor_type => @project.owner.class.to_s, :role => 'admin'
- @create_params[:owner_name] = @user.uname; @update_params[:owner_name] = @user.uname
+ set_session_for(@project.owner) # owner should be user
end
it_should_behave_like 'user with create comment rights'
diff --git a/spec/controllers/projects/git/git_trees_controller_spec.rb b/spec/controllers/projects/git/git_trees_controller_spec.rb
index f2baf5020..5bf420e11 100644
--- a/spec/controllers/projects/git/git_trees_controller_spec.rb
+++ b/spec/controllers/projects/git/git_trees_controller_spec.rb
@@ -12,22 +12,22 @@ describe Projects::Git::TreesController do
@project = FactoryGirl.create(:project)
@another_user = FactoryGirl.create(:user)
- @params = {:owner_name => @project.owner.uname, :project_name => @project.name, :treeish => 'master'}
+ @params = { :owner_name => @project.owner.uname,
+ :project_name => @project.name,
+ :treeish => "#{@project.owner.uname}-#{@project.name}-master"}
end
context 'for guest' do
- if APP_CONFIG['anonymous_access']
- it 'should be able to perform archive action with anonymous acccess' do
- fill_project
- get :archive, @params.merge(:format => 'tar')
- response.should be_success
- end
- else
- it 'should not be able to perform archive action without anonymous acccess' do
- fill_project
- get :archive, @params.merge(:format => 'tar')
- response.code.should == '401'
- end
+ it 'should be able to perform archive action with anonymous acccess', :anonymous_access => true do
+ fill_project
+ get :archive, @params.merge(:format => 'tar.gz')
+ response.should be_success
+ end
+
+ it 'should not be able to perform archive action without anonymous acccess', :anonymous_access => false do
+ fill_project
+ get :archive, @params.merge(:format => 'tar.gz')
+ response.code.should == '401'
end
end
@@ -35,14 +35,14 @@ describe Projects::Git::TreesController do
it 'should not be able to archive empty project' do
@user = FactoryGirl.create(:user)
set_session_for(@user)
- expect { get :archive, @params.merge(:format => 'tar') }.to raise_error(ActionController::RoutingError)
+ expect { get :archive, @params.merge(:format => 'tar.gz') }.to raise_error(ActionController::RoutingError)
end
it 'should not be able to injection code with format' do
@user = FactoryGirl.create(:user)
set_session_for(@user)
fill_project
- expect { get :archive, @params.merge(:format => "tar master > /dev/null; echo 'I am hacker!';\#") }.to raise_error(ActionController::RoutingError)
+ expect { get :archive, @params.merge(:format => "tar.gz master > /dev/null; echo 'I am hacker!';\#") }.to raise_error(ActionController::RoutingError)
end
it 'should not be able to injection code with treeish' do
@@ -56,7 +56,7 @@ describe Projects::Git::TreesController do
@user = FactoryGirl.create(:user)
set_session_for(@user)
fill_project
- get :archive, @params.merge(:format => 'tar')
+ get :archive, @params.merge(:format => 'tar.gz')
response.should be_success
end
end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index 49a6e9b07..65873a0a3 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -1,7 +1,43 @@
# -*- encoding : utf-8 -*-
require 'spec_helper'
-shared_examples_for 'issue user with project reader rights' do
+shared_context "issues controller" do
+ before(:each) do
+ stub_symlink_methods
+
+ @project = FactoryGirl.create(:project)
+ @issue_user = FactoryGirl.create(:user)
+
+ @issue = FactoryGirl.create(:issue, :project_id => @project.id, :assignee_id => @issue_user.id)
+
+ @project_with_turned_off_issues = FactoryGirl.create(:project, :has_issues => false)
+ @turned_of_issue = FactoryGirl.create(:issue, :project_id => @project_with_turned_off_issues.id, :assignee_id => @issue_user.id)
+
+ @user = FactoryGirl.create(:user)
+ set_session_for(@user)
+
+ @create_params = {
+ :owner_name => @project.owner.uname, :project_name => @project.name,
+ :issue => {
+ :title => "issue1",
+ :body => "issue body"
+ },
+ :assignee_id => @issue_user.id,
+ :assignee_uname => @issue_user.uname
+ }
+
+ @update_params = {
+ :owner_name => @project.owner.uname, :project_name => @project.name,
+ :issue => {
+ :title => "issue2"
+ }
+ }
+
+ end
+
+end
+
+shared_examples_for 'issue user with project guest rights' do
it 'should be able to perform index action' do
get :index, :owner_name => @project.owner.uname, :project_name => @project.name
response.should render_template(:index)
@@ -11,9 +47,12 @@ shared_examples_for 'issue user with project reader rights' do
get :show, :owner_name => @project.owner.uname, :project_name => @project.name, :id => @issue.serial_id
response.should render_template(:show)
end
+end
+
+shared_examples_for 'issue user with project reader rights' do
it 'should be able to perform index action on hidden project' do
- @project.update_attribute :visibility, 'hidden'
+ @project.update_attributes(:visibility => 'hidden')
get :index, :owner_name => @project.owner.uname, :project_name => @project.name
response.should render_template(:index)
end
@@ -66,9 +105,9 @@ shared_examples_for 'user without issue destroy rights' do
end
shared_examples_for 'project with issues turned off' do
- pending 'should not be able to perform index action' do
+ it 'should not be able to perform index action' do
get :index, :project_id => @project_with_turned_off_issues.id
- response.should render_template(:index)
+ response.should redirect_to(forbidden_path)
end
it 'should not be able to perform show action' do
@@ -78,107 +117,82 @@ shared_examples_for 'project with issues turned off' do
end
describe Projects::IssuesController do
- before(:each) do
- stub_symlink_methods
-
- @project = FactoryGirl.create(:project)
- @issue_user = FactoryGirl.create(:user)
-
- any_instance_of(Project, :versions => ['v1.0', 'v2.0'])
-
- @issue = FactoryGirl.create(:issue, :project_id => @project.id, :assignee_id => @issue_user.id)
- @create_params = {
- :owner_name => @project.owner.uname, :project_name => @project.name,
- :issue => {
- :title => "issue1",
- :body => "issue body"
- },
- :assignee_id => @issue_user.id,
- :assignee_uname => @issue_user.uname
- }
- @update_params = {
- :owner_name => @project.owner.uname, :project_name => @project.name,
- :issue => {
- :title => "issue2"
- }
- }
-
- @project_with_turned_off_issues = FactoryGirl.create(:project, :has_issues => false)
- @turned_of_issue = FactoryGirl.create(:issue, :project_id => @project_with_turned_off_issues.id, :assignee_id => @issue_user.id)
- end
+ include_context "issues controller"
context 'for global admin user' do
before(:each) do
- @admin = FactoryGirl.create(:admin)
- set_session_for(@admin)
+ @user.role = "admin"
+ @user.save
end
+ it_should_behave_like 'issue user with project guest rights'
+ it_should_behave_like 'issue user with project reader rights'
+ it_should_behave_like 'issue user with project writer rights'
+ it_should_behave_like 'user with issue update rights'
+ it_should_behave_like 'project with issues turned off'
it_should_behave_like 'user without issue destroy rights'
end
context 'for project admin user' do
before(:each) do
- @user = FactoryGirl.create(:user)
- set_session_for(@user)
@project.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
end
+ it_should_behave_like 'issue user with project guest rights'
it_should_behave_like 'issue user with project reader rights'
it_should_behave_like 'issue user with project writer rights'
it_should_behave_like 'user with issue update rights'
- it_should_behave_like 'user without issue destroy rights'
it_should_behave_like 'project with issues turned off'
+ it_should_behave_like 'user without issue destroy rights'
end
context 'for project owner user' do
before(:each) do
- @user = FactoryGirl.create(:user)
+ @user = @project.owner
set_session_for(@user)
- @project.update_attribute(:owner, @user); @create_params[:owner_name] = @user.uname; @update_params[:owner_name] = @user.uname
- @project.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
end
+ it_should_behave_like 'issue user with project guest rights'
it_should_behave_like 'issue user with project reader rights'
it_should_behave_like 'issue user with project writer rights'
it_should_behave_like 'user with issue update rights'
- it_should_behave_like 'user without issue destroy rights'
it_should_behave_like 'project with issues turned off'
+ it_should_behave_like 'user without issue destroy rights'
end
context 'for project reader user' do
before(:each) do
- @user = FactoryGirl.create(:user)
- set_session_for(@user)
@project.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'reader')
end
+ it_should_behave_like 'issue user with project guest rights'
it_should_behave_like 'issue user with project reader rights'
+ it_should_behave_like 'issue user with project writer rights'
it_should_behave_like 'user without issue update rights'
- it_should_behave_like 'user without issue destroy rights'
it_should_behave_like 'project with issues turned off'
+ it_should_behave_like 'user without issue destroy rights'
- it 'should not be able to perform create action' do
- post :create, @create_params
- response.should redirect_to(forbidden_path)
- end
+ # it 'should not be able to perform create action on project' do
+ # post :create, @create_params
+ # response.should redirect_to(forbidden_path)
+ # end
- it 'should not create issue object into db' do
- lambda{ post :create, @create_params }.should change{ Issue.count }.by(0)
- end
+ # it 'should not create issue object into db' do
+ # lambda{ post :create, @create_params }.should change{ Issue.count }.by(0)
+ # end
end
context 'for project writer user' do
before(:each) do
- @user = FactoryGirl.create(:user)
- set_session_for(@user)
@project.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'writer')
end
+ it_should_behave_like 'issue user with project guest rights'
it_should_behave_like 'issue user with project reader rights'
it_should_behave_like 'issue user with project writer rights'
it_should_behave_like 'user without issue update rights'
- it_should_behave_like 'user without issue destroy rights'
it_should_behave_like 'project with issues turned off'
+ it_should_behave_like 'user without issue destroy rights'
end
context 'for issue assign user' do
@@ -187,28 +201,26 @@ describe Projects::IssuesController do
end
it_should_behave_like 'user without issue update rights'
- it_should_behave_like 'user without issue destroy rights'
it_should_behave_like 'project with issues turned off'
+ it_should_behave_like 'user without issue destroy rights'
end
context 'for guest' do
+
+ before(:each) do
+ set_session_for(User.new)
+ end
+
if APP_CONFIG['anonymous_access']
- # it_should_behave_like 'issue user with project reader rights'
- it 'should be able to perform index action' do
- get :index, :owner_name => @project.owner.uname, :project_name => @project.name
- response.should render_template(:index)
- end
-
- it 'should be able to perform show action' do
- get :show, :owner_name => @project.owner.uname, :project_name => @project.name, :id => @issue.serial_id
- response.should render_template(:show)
- end
-
+
+ it_should_behave_like 'issue user with project guest rights'
+
it 'should not be able to perform index action on hidden project' do
- @project.update_attribute :visibility, 'hidden'
+ @project.update_attributes(:visibility => 'hidden')
get :index, :owner_name => @project.owner.uname, :project_name => @project.name
response.should redirect_to(forbidden_path)
end
+
else
it 'should not be able to perform index action' do
get :index, :owner_name => @project.owner.uname, :project_name => @project.name
@@ -221,7 +233,7 @@ describe Projects::IssuesController do
end
it 'should not be able to perform index action on hidden project' do
- @project.update_attribute :visibility, 'hidden'
+ @project.update_attributes(:visibility => 'hidden')
get :index, :owner_name => @project.owner.uname, :project_name => @project.name
response.should redirect_to(new_user_session_path)
end
diff --git a/spec/controllers/projects/projects_controller_spec.rb b/spec/controllers/projects/projects_controller_spec.rb
index a94cced96..dc240686a 100644
--- a/spec/controllers/projects/projects_controller_spec.rb
+++ b/spec/controllers/projects/projects_controller_spec.rb
@@ -1,217 +1,277 @@
# -*- encoding : utf-8 -*-
require 'spec_helper'
+shared_examples_for 'projects user with reader rights' do
+
+ it 'should be able to fork project' do
+ post :fork, :owner_name => @project.owner.uname, :project_name => @project.name
+ response.should redirect_to(project_path(Project.last))
+ end
+
+ it 'should be able to fork project to their group' do
+ group = FactoryGirl.create(:group)
+ group.actors.create(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
+ lambda {post :fork, :owner_name => @project.owner.uname, :project_name => @project.name,
+ :group => group.id}.should change{ Project.count }.by(1)
+ end
+
+ it 'should be able to fork project to own group' do
+ group = FactoryGirl.create(:group, :owner => @user)
+ lambda {post :fork, :owner_name => @project.owner.uname, :project_name => @project.name,
+ :group => group.id}.should change{ Project.count }.by(1)
+ end
+
+ # it 'should be able to view project' do
+ # get :show, :owner_name => @project.owner.uname, :project_name => @project.name
+ # assigns(:project).should eq @project
+ # end
+
+end
+
+shared_examples_for 'projects user with project admin rights' do
+ it 'should be able to perform update action' do
+ put :update, {:owner_name => @project.owner.uname, :project_name => @project.name}.merge(@update_params)
+ response.should redirect_to(project_path(@project))
+ end
+end
+
+shared_examples_for 'user with destroy rights' do
+ it 'should be able to perform destroy action' do
+ delete :destroy, {:owner_name => @project.owner.uname, :project_name => @project.name}
+ response.should redirect_to(@project.owner)
+ end
+
+ it 'should change objects count on destroy' do
+ lambda { delete :destroy, :owner_name => @project.owner.uname, :project_name => @project.name }.should change{ Project.count }.by(-1)
+ end
+end
+
+shared_examples_for 'projects user without project admin rights' do
+ it 'should not be able to edit project' do
+ description = @project.description
+ put :update, :project=>{:description =>"hack"}, :owner_name => @project.owner.uname, :project_name => @project.name
+ @project.reload.description.should == description
+ response.should redirect_to(forbidden_path)
+ end
+
+ it 'should not be able to edit project sections' do
+ has_wiki, has_issues = @project.has_wiki, @project.has_issues
+ post :sections, :project =>{:has_wiki => !has_wiki, :has_issues => !has_issues}, :owner_name => @project.owner.uname, :project_name => @project.name
+ @project.reload.has_wiki.should == has_wiki
+ @project.reload.has_issues.should == has_issues
+ response.should redirect_to(forbidden_path)
+ end
+end
+
describe Projects::ProjectsController do
before(:each) do
stub_symlink_methods
@project = FactoryGirl.create(:project)
- @another_user = FactoryGirl.create(:user)
+
@create_params = {:project => {:name => 'pro'}}
@update_params = {:project => {:description => 'pro2'}}
+
+ @user = FactoryGirl.create(:user)
+ set_session_for(@user)
end
- context 'for guest' do
- it 'should not be able to perform index action' do
- get :index
- response.should redirect_to(new_user_session_path)
+ context 'for system users' do
+
+ context 'guest' do
+
+ before(:each) do
+ set_session_for(User.new)
+ end
+
+ it 'should not be able to perform index action' do
+ get :index
+ response.should redirect_to(new_user_session_path)
+ end
+
+ it 'should not be able to perform update action' do
+ put :update, {:owner_name => @project.owner.uname, :project_name => @project.name}.merge(@update_params)
+ response.should redirect_to(new_user_session_path)
+ end
end
- it 'should not be able to perform update action' do
- put :update, {:owner_name => @project.owner.uname, :project_name => @project.name}.merge(@update_params)
- response.should redirect_to(new_user_session_path)
- end
- end
+ context 'registered user' do
+
+ it 'should be able to perform index action' do
+ get :index
+ response.should render_template(:index)
+ end
+
+ context 'create project for myself' do
+
+ it 'should be able to perform create action' do
+ post :create, @create_params
+ response.should redirect_to(project_path( Project.last ))
+ end
+
+ it 'should create project in the database' do
+ lambda { post :create, @create_params }.should change{ Project.count }.by(1)
+ end
+ end
+
+ context 'create project for group' do
+
+ it 'should not be able to create project for alien group' do
+ group = FactoryGirl.create(:group)
+ post :create, @create_params.merge({:who_owns => 'group', :owner_id => group.id})
+ response.should redirect_to(forbidden_path)
+ end
+
+ it 'should be able to create project for their group' do
+ group = FactoryGirl.create(:group)
+ group.actors.create(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
+ lambda { post :create, @create_params.merge({:who_owns => 'group', :owner_id => group.id})}.should change{ Project.count }.by(1)
+ end
+
+ it 'should be able to create project for own group' do
+ group = FactoryGirl.create(:group, :owner => @user)
+ lambda { post :create, @create_params.merge({:who_owns => 'group', :owner_id => group.id})}.should change{ Project.count }.by(1)
+ end
+
+ end
+
+ end # context 'registered user'
+ end # context 'for system users'
+
+ context 'for project members' do
+
+ context 'for global admin' do
+ before(:each) do
+ @user.role = "admin"
+ @user.save
+ set_session_for(@user)
+ end
+
+ it_should_behave_like 'projects user with project admin rights'
+ it_should_behave_like 'projects user with reader rights'
+ it_should_behave_like 'user with destroy rights'
- context 'for admin' do
- before(:each) do
- @admin = FactoryGirl.create(:admin)
- set_session_for(@admin)
end
- it_should_behave_like 'projects user with admin rights'
- it_should_behave_like 'projects user with reader rights'
+ context 'for owner user' do
+ before(:each) do
+ @user = @project.owner
+ set_session_for(@user) # owner should be user
+ end
+
+ it_should_behave_like 'projects user with project admin rights'
+ it_should_behave_like 'projects user with reader rights'
+ it_should_behave_like 'user with destroy rights'
+
+ it 'should not be able to fork own project' do
+ post :fork, :owner_name => @project.owner.uname, :project_name => @project.name
+ response.should redirect_to(@project)
+ end
- it 'should be able to perform create action' do
- post :create, @create_params
- response.should redirect_to(project_path( Project.last ))
end
- it 'should change objects count on create' do
- lambda { post :create, @create_params }.should change{ Project.count }.by(1)
- end
- end
+ context 'for reader user' do
+ before(:each) do
+ @project.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'reader')
+ end
- context 'for owner user' do
- before(:each) do
- @user = FactoryGirl.create(:user)
- set_session_for(@user)
- @project.update_attribute(:owner, @user)
- @project.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
+ it_should_behave_like 'projects user with reader rights'
+ it_should_behave_like 'projects user without project admin rights'
end
- it_should_behave_like 'projects user with admin rights'
- it_should_behave_like 'user with rights to view projects'
+ context 'for writer user' do
+ before(:each) do
+ @project.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'writer')
+ end
+
+ it_should_behave_like 'projects user with reader rights'
+ it_should_behave_like 'projects user without project admin rights'
- it 'should be able to perform destroy action' do
- delete :destroy, {:owner_name => @project.owner.uname, :project_name => @project.name}
- response.should redirect_to(@project.owner)
end
- it 'should change objects count on destroy' do
- lambda { delete :destroy, :owner_name => @project.owner.uname, :project_name => @project.name }.should change{ Project.count }.by(-1)
+ context 'for other user' do
+
+ it 'should not be able to fork hidden project' do
+ @project.update_attributes(:visibility => 'hidden')
+ post :fork, :owner_name => @project.owner.uname, :project_name => @project.name
+ response.should redirect_to(forbidden_path)
+ end
+
+ it_should_behave_like 'projects user without project admin rights'
+
end
- it 'should not be able to fork project' do
- post :fork, :owner_name => @project.owner.uname, :project_name => @project.name
- # @project.errors.count.should == 1
- response.should redirect_to(@project)
- end
-
- end
-
- context 'for reader user' do
- before(:each) do
- @user = FactoryGirl.create(:user)
- set_session_for(@user)
- @project.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'reader')
- end
-
- it_should_behave_like 'projects user with reader rights'
- it_should_behave_like 'user without update rights'
- end
-
- context 'for writer user' do
- before(:each) do
- @user = FactoryGirl.create(:user)
- set_session_for(@user)
- @project.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'writer')
- end
-
- it_should_behave_like 'projects user with reader rights'
-
- it 'should not be able to create project to other group' do
- group = FactoryGirl.create(:group)
- post :create, @create_params.merge({:who_owns => 'group', :owner_id => group.id})
- response.should redirect_to(forbidden_path)
- end
-
- it 'should not be able to fork project to other group' do
- group = FactoryGirl.create(:group)
- post :fork, :owner_name => @project.owner.uname, :project_name => @project.name, :group => group.id
- response.should redirect_to(forbidden_path)
- end
-
- it 'should be able to fork project to group' do
- group = FactoryGirl.create(:group)
- group.actors.create(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
- post :fork, :owner_name => @project.owner.uname, :project_name => @project.name, :group => group.id
- response.should redirect_to(project_path(group.projects.first))
- end
- end
-
- context 'search projects' do
- before(:each) do
- @admin = FactoryGirl.create(:admin)
- @project1 = FactoryGirl.create(:project, :name => 'perl-debug')
- @project2 = FactoryGirl.create(:project, :name => 'perl')
- set_session_for(@admin)
- end
-
- pending 'should return projects in right order' do
- get :index, :query => 'per'
- assigns(:projects).should eq([@project2, @project1])
- end
- end
-
- context 'for other user' do
- before(:each) do
- @user = FactoryGirl.create(:user)
- set_session_for(@user)
- end
-
- it 'should not be able to fork hidden project' do
- @project.update_attribute(:visibility, 'hidden')
- post :fork, :owner_name => @project.owner.uname, :project_name => @project.name
- response.should redirect_to(forbidden_path)
- end
-
- it_should_behave_like 'user without update rights'
- end
+ end # context 'for project members'
context 'for group' do
before(:each) do
@group = FactoryGirl.create(:group)
- @group_user = FactoryGirl.create(:user)
- @project.relations.destroy_all
- set_session_for(@group_user)
end
- context 'owner of the project' do
+ context 'group is owner of the project' do
before(:each) do
- @project.update_attribute :owner, @group
- @project.relations.create :actor_id => @project.owner.id, :actor_type => @project.owner.class.to_s, :role => 'admin'
+ @project = FactoryGirl.create(:project, :owner => @group)
end
- context 'reader user' do
+ context 'group member user with reader role' do
before(:each) do
- @group.actors.create(:actor_id => @group_user.id, :actor_type => 'User', :role => 'reader')
+ @group.actors.create(:actor_id => @user.id, :actor_type => 'User', :role => 'reader')
end
it_should_behave_like 'projects user with reader rights'
- it_should_behave_like 'user without update rights'
+ it_should_behave_like 'projects user without project admin rights'
it 'should has reader role to group project' do
- @group_user.best_role(@project).should eql('reader') # Need this?
+ @user.best_role(@project).should eql('reader')
end
context 'user should has best role' do
before(:each) do
- @project.relations.create :actor_id => @group_user.id, :actor_type => @group_user.class.to_s, :role => 'admin'
+ @project.relations.create :actor_id => @user.id, :actor_type => @user.class.to_s, :role => 'admin'
end
- it_should_behave_like 'projects user with admin rights'
+ it_should_behave_like 'projects user with project admin rights'
end
end
- context 'admin user' do
+ context 'group member user with admin role' do
before(:each) do
- @group.actors.create(:actor_id => @group_user.id, :actor_type => 'User', :role => 'admin')
+ @group.actors.create(:actor_id => @user.id, :actor_type => 'User', :role => 'admin')
end
- it_should_behave_like 'projects user with admin rights'
+ it_should_behave_like 'projects user with project admin rights'
it_should_behave_like 'projects user with reader rights'
end
end
- context 'member of the project' do
+ context 'group is member of the project' do
context 'with admin rights' do
before(:each) do
@project.relations.create :actor_id => @group.id, :actor_type => @group.class.to_s, :role => 'admin'
end
- context 'reader user' do
+ context 'group member user with reader role' do
before(:each) do
- @group.actors.create(:actor_id => @group_user.id, :actor_type => 'User', :role => 'reader')
+ @group.actors.create(:actor_id => @user.id, :actor_type => 'User', :role => 'reader')
end
it_should_behave_like 'projects user with reader rights'
- it_should_behave_like 'projects user with admin rights'
+ it_should_behave_like 'projects user with project admin rights'
context 'user should has best role' do
before(:each) do
- @project.relations.create :actor_id => @group_user.id, :actor_type => @group_user.class.to_s, :role => 'reader'
+ @project.relations.create :actor_id => @user.id, :actor_type => @user.class.to_s, :role => 'reader'
end
- it_should_behave_like 'projects user with admin rights'
+ it_should_behave_like 'projects user with project admin rights'
end
end
- context 'admin user' do
+ context 'group member user with admin role' do
before(:each) do
- @group.actors.create(:actor_id => @group_user.id, :actor_type => 'User', :role => 'admin')
+ @group.actors.create(:actor_id => @user.id, :actor_type => 'User', :role => 'admin')
end
- it_should_behave_like 'projects user with admin rights'
+ it_should_behave_like 'projects user with project admin rights'
it_should_behave_like 'projects user with reader rights'
end
end
@@ -221,29 +281,29 @@ describe Projects::ProjectsController do
@project.relations.create :actor_id => @group.id, :actor_type => @group.class.to_s, :role => 'reader'
end
- context 'reader user' do
+ context 'group member user with reader role' do
before(:each) do
- @group.actors.create(:actor_id => @group_user.id, :actor_type => 'User', :role => 'reader')
+ @group.actors.create(:actor_id => @user.id, :actor_type => 'User', :role => 'reader')
end
it_should_behave_like 'projects user with reader rights'
- it_should_behave_like 'user without update rights'
+ it_should_behave_like 'projects user without project admin rights'
context 'user should has best role' do
before(:each) do
- @project.relations.create :actor_id => @group_user.id, :actor_type => @group_user.class.to_s, :role => 'admin'
+ @project.relations.create :actor_id => @user.id, :actor_type => @user.class.to_s, :role => 'admin'
end
- it_should_behave_like 'projects user with admin rights'
+ it_should_behave_like 'projects user with project admin rights'
end
end
- context 'admin user' do
+ context 'group member user with admin role' do
before(:each) do
- @group.actors.create(:actor_id => @group_user.id, :actor_type => 'User', :role => 'admin')
+ @group.actors.create(:actor_id => @user.id, :actor_type => 'User', :role => 'admin')
end
it_should_behave_like 'projects user with reader rights'
- it_should_behave_like 'user without update rights'
+ it_should_behave_like 'projects user without project admin rights'
end
end
end
diff --git a/spec/factories/build_lists.rb b/spec/factories/build_lists.rb
index 0271f50ea..5f2b0d574 100644
--- a/spec/factories/build_lists.rb
+++ b/spec/factories/build_lists.rb
@@ -6,6 +6,7 @@ FactoryGirl.define do
association :save_to_platform, :factory => :platform_with_repos
association :arch
build_for_platform {|bl| bl.save_to_platform}
+ save_to_repository {|bl| bl.save_to_platform.repositories.first}
project_version "1.0"
build_requires true
update_type 'security'
diff --git a/spec/factories/product_build_lists.rb b/spec/factories/product_build_lists.rb
index ef7642340..9e99cbcc1 100644
--- a/spec/factories/product_build_lists.rb
+++ b/spec/factories/product_build_lists.rb
@@ -2,5 +2,6 @@
FactoryGirl.define do
factory :product_build_list do
association :product, :factory => :product
+ status 0 # BUILD_COMPLETED
end
end
diff --git a/spec/models/build_list_spec.rb b/spec/models/build_list_spec.rb
new file mode 100644
index 000000000..421e39726
--- /dev/null
+++ b/spec/models/build_list_spec.rb
@@ -0,0 +1,146 @@
+# -*- encoding : utf-8 -*-
+require 'spec_helper'
+
+describe BuildList do
+
+ context "#notify_users" do
+ before { stub_symlink_methods }
+ let!(:user) { FactoryGirl.create(:user) }
+ let!(:build_list) { FactoryGirl.create(:build_list_core,
+ :user => user,
+ :auto_publish => false) }
+ let!(:build_list_package) { FactoryGirl.create(:build_list_package,
+ :build_list => build_list,
+ :project => build_list.project) }
+
+
+ before(:all) { ActionMailer::Base.deliveries = [] }
+ before do
+ test_git_commit(build_list.project)
+ build_list.update_attributes(:commit_hash => build_list.project.repo.commits('master').last.id,
+ :status => BuildServer::BUILD_STARTED,)
+ end
+ after { ActionMailer::Base.deliveries = [] }
+
+ shared_examples_for 'build list notifications by email' do
+ it "gets notification by email when status - Build complete" do
+ build_list.build_success
+ should have(1).item
+ end
+
+ it "gets notification by email when status - Build error" do
+ build_list.build_error
+ should have(1).item
+ end
+
+ it "gets notification by email when auto_publish and status - Build error" do
+ build_list.update_attributes(:auto_publish => true)
+ build_list.build_error
+ should have(1).item
+ end
+
+ it "gets notification by email when status - Failed publish" do
+ build_list.update_attributes(:status => BuildList::BUILD_PUBLISH)
+ build_list.fail_publish
+ should have(1).item
+ end
+
+ it "gets notification by email when auto_publish and status - Failed publish" do
+ build_list.update_attributes(:auto_publish => true, :status => BuildList::BUILD_PUBLISH)
+ build_list.fail_publish
+ should have(1).item
+ end
+
+ it "gets notification by email when status - Build published" do
+ build_list.update_attributes(:status => BuildList::BUILD_PUBLISH)
+ build_list.published
+ should have(1).item
+ end
+
+ it "gets notification by email when auto_publish and status - Build published" do
+ build_list.update_attributes(:auto_publish => true, :status => BuildList::BUILD_PUBLISH)
+ build_list.published
+ should have(1).item
+ end
+
+ it "doesn't get notification by email when auto_publish and status - Build complete" do
+ build_list.update_attributes(:auto_publish => true)
+ build_list.build_success
+ should have(:no).items
+ end
+
+ it "doesn't get notification by email when mass build" do
+ build_list.update_attributes(:mass_build_id => 1, :status => BuildList::BUILD_PUBLISH)
+ build_list.published
+ should have(:no).items
+ end
+
+ it "doesn't get notification by email when notification by email has been disabled" do
+ notifier.update_attributes(:can_notify => false)
+ build_list.build_success
+ should have(:no).items
+ end
+ end
+
+ subject { ActionMailer::Base.deliveries }
+
+ context "user created build task" do
+ let!(:notifier) { user.notifier }
+ before do
+ notifier.update_attributes(:new_associated_build => false)
+ build_list.project.owner.notifier.update_attributes(:can_notify => false)
+ end
+
+ it_should_behave_like 'build list notifications by email'
+
+ it "doesn't get notification by email when 'build list' notifications has been disabled" do
+ notifier.update_attributes(:new_build => false)
+ build_list.build_success
+ should have(:no).items
+ end
+
+ it "doesn't get notification by email when 'build list' notifications - enabled, email notifications - disabled" do
+ notifier.update_attributes(:can_notify => false, :new_build => true)
+ build_list.build_success
+ should have(:no).items
+ end
+ end
+
+ context "build task has been created and associated user" do
+ let!(:notifier) { build_list.project.owner.notifier }
+ before do
+ notifier.update_attributes(:new_build => false)
+ user.notifier.update_attributes(:can_notify => false)
+ end
+
+ it_should_behave_like 'build list notifications by email'
+
+ it "doesn't get notification by email when 'associated build list' notifications has been disabled" do
+ notifier.update_attributes(:new_associated_build => false)
+ build_list.build_success
+ should have(:no).items
+ end
+
+ it "doesn't get notification by email when 'associated build list' notifications - enabled, email notifications - disabled" do
+ notifier.update_attributes(:can_notify => false, :new_associated_build => true)
+ build_list.build_success
+ should have(:no).items
+ end
+ end
+
+ it "doesn't get 2 notification by email when user associated to project and created task" do
+ bl = FactoryGirl.create(:build_list_core,
+ :user => user,
+ :auto_publish => true,
+ :project => FactoryGirl.create(:project, :owner => user))
+ FactoryGirl.create(:build_list_package, :build_list => bl, :project => bl.project)
+ test_git_commit(bl.project)
+ bl.update_attributes(:commit_hash => bl.project.repo.commits('master').last.id,
+ :status => BuildList::BUILD_PUBLISH)
+ bl.published
+ should have(1).item
+ end
+
+ end # notify_users
+
+end
diff --git a/spec/models/cancan_spec.rb b/spec/models/cancan_spec.rb
index 467b1e275..5f0ba821a 100644
--- a/spec/models/cancan_spec.rb
+++ b/spec/models/cancan_spec.rb
@@ -103,15 +103,15 @@ describe CanCan do
@ability.should be_able_to(:read, @admin)
end
- pending "shoud be able to read index AutoBuildList" do
- @ability.should be_able_to(:index, AutoBuildList)
- end
-
it "shoud be able to read open projects" do
@project = FactoryGirl.create(:project, :visibility => 'open')
@ability.should be_able_to(:read, @project)
end
+ it 'should be able to see open platform' do
+ @ability.should be_able_to(:show, open_platform)
+ end
+
it "shoud be able to create project" do
@ability.should be_able_to(:create, Project)
end
@@ -123,7 +123,9 @@ describe CanCan do
context "private users relations" do
before(:each) do
@private_user = FactoryGirl.create(:private_user)
- @private_user.platform.update_attribute(:owner, @user)
+
+ @private_user.platform.owner = @user
+ @private_user.platform.save
end
[:read, :create].each do |action|
@@ -148,10 +150,6 @@ describe CanCan do
@ability.should be_able_to(:read, @project)
end
- it 'should be able to read open platform' do
- @ability.should be_able_to(:read, open_platform)
- end
-
it 'should be able to read issue' do
@ability.should be_able_to(:read, @issue)
end
@@ -207,7 +205,9 @@ describe CanCan do
context 'with owner rights' do
before(:each) do
- @project.update_attribute(:owner, @user)
+ @project.owner = @user
+ @project.save
+
@project.relations.create!(:actor_id => @user.id, :actor_type => 'User', :role => 'admin')
@issue.project.reload
end
@@ -241,7 +241,8 @@ describe CanCan do
context 'with owner rights' do
before(:each) do
- @platform.update_attribute(:owner, @user)
+ @platform.owner = @user
+ @platform.save
end
[:read, :update, :destroy].each do |action|
@@ -269,7 +270,8 @@ describe CanCan do
context 'with owner rights' do
before(:each) do
- @repository.platform.update_attribute(:owner, @user)
+ @repository.platform.owner = @user
+ @repository.platform.save
end
[:read, :create, :update, :destroy, :add_project, :remove_project, :change_visibility, :settings].each do |action|
diff --git a/spec/models/comment_for_commit_spec.rb b/spec/models/comment_for_commit_spec.rb
index b56769e26..c27479215 100644
--- a/spec/models/comment_for_commit_spec.rb
+++ b/spec/models/comment_for_commit_spec.rb
@@ -91,7 +91,7 @@ describe Comment do
context 'for disabled notify setting new_comment_commit_repo_owner' do
it 'should not send an e-mail' do
- @user.notifier.update_attribute :new_comment_commit_repo_owner, false
+ @user.notifier.update_column :new_comment_commit_repo_owner, false
comment = create_comment(@stranger)
ActionMailer::Base.deliveries.count.should == 1
end
@@ -99,7 +99,7 @@ describe Comment do
context 'for disabled notify setting new_comment_commit_owner' do
it 'should send an e-mail' do
- @user.notifier.update_attribute :new_comment_commit_owner, false
+ @user.notifier.update_column :new_comment_commit_owner, false
comment = create_comment(@stranger)
ActionMailer::Base.deliveries.count.should == 1
ActionMailer::Base.deliveries.last.to.include?(@user.email).should == true
@@ -108,7 +108,7 @@ describe Comment do
context 'for disabled notify setting new_comment_commit_commentor' do
it 'should send an e-mail' do
- @user.notifier.update_attribute :new_comment_commit_commentor, false
+ @user.notifier.update_column :new_comment_commit_commentor, false
comment = create_comment(@stranger)
ActionMailer::Base.deliveries.count.should == 1
ActionMailer::Base.deliveries.last.to.include?(@user.email).should == true
@@ -117,9 +117,9 @@ describe Comment do
context 'for disabled all notify setting expect global' do
it 'should not send an e-mail' do
- @user.notifier.update_attribute :new_comment_commit_repo_owner, false
- @user.notifier.update_attribute :new_comment_commit_owner, false
- @user.notifier.update_attribute :new_comment_commit_commentor, false
+ @user.notifier.update_column :new_comment_commit_repo_owner, false
+ @user.notifier.update_column :new_comment_commit_owner, false
+ @user.notifier.update_column :new_comment_commit_commentor, false
comment = create_comment(@stranger)
ActionMailer::Base.deliveries.count.should == 0
end
@@ -135,7 +135,7 @@ describe Comment do
context 'for disabled global notify setting' do
it 'should not send an e-mail' do
- @user.notifier.update_attribute :can_notify, false
+ @user.notifier.update_column :can_notify, false
comment = create_comment(@stranger)
ActionMailer::Base.deliveries.count.should == 0
end
@@ -148,7 +148,10 @@ describe Comment do
@user = FactoryGirl.create(:user)
@stranger = FactoryGirl.create(:user)
set_comments_data_for_commit
- @project.update_attribute(:owner, @user)
+
+ @project.owner = @user
+ @project.save
+
ActionMailer::Base.deliveries = []
end
@@ -178,7 +181,7 @@ describe Comment do
context 'for disabled notify setting new_comment_commit_repo_owner' do
it 'should not send an e-mail' do
- @user.notifier.update_attribute :new_comment_commit_repo_owner, false
+ @user.notifier.update_column :new_comment_commit_repo_owner, false
Comment.destroy_all
comment = create_comment(@stranger)
ActionMailer::Base.deliveries.count.should == 0
@@ -187,7 +190,7 @@ describe Comment do
context 'for disabled notify setting new_comment_commit_owner' do
it 'should send an e-mail' do
- @user.notifier.update_attribute :new_comment_commit_owner, false
+ @user.notifier.update_column :new_comment_commit_owner, false
comment = create_comment(@stranger)
ActionMailer::Base.deliveries.count.should == 1
ActionMailer::Base.deliveries.last.to.include?(@user.email).should == true
@@ -196,7 +199,7 @@ describe Comment do
context 'for disabled notify setting new_comment_commit_commentor' do
it 'should send an e-mail' do
- @user.notifier.update_attribute :new_comment_commit_commentor, false
+ @user.notifier.update_column :new_comment_commit_commentor, false
comment = create_comment(@stranger)
ActionMailer::Base.deliveries.count.should == 1
ActionMailer::Base.deliveries.last.to.include?(@user.email).should == true
@@ -205,9 +208,9 @@ describe Comment do
context 'for disabled all notify setting expect global' do
it 'should not send an e-mail' do
- @user.notifier.update_attribute :new_comment_commit_repo_owner, false
- @user.notifier.update_attribute :new_comment_commit_owner, false
- @user.notifier.update_attribute :new_comment_commit_commentor, false
+ @user.notifier.update_column :new_comment_commit_repo_owner, false
+ @user.notifier.update_column :new_comment_commit_owner, false
+ @user.notifier.update_column :new_comment_commit_commentor, false
comment = create_comment(@stranger)
ActionMailer::Base.deliveries.count.should == 0
end
@@ -223,7 +226,7 @@ describe Comment do
context 'for disabled global notify setting' do
it 'should not send an e-mail' do
- @user.notifier.update_attribute :can_notify, false
+ @user.notifier.update_column :can_notify, false
comment = create_comment(@stranger)
ActionMailer::Base.deliveries.count.should == 0
end
@@ -231,7 +234,7 @@ describe Comment do
context 'for own commit' do
it 'should send a one e-mail' do
- @project.owner.update_attribute :email, 'code@tpope.net'
+ @project.owner.update_column :email, 'code@tpope.net'
comment = create_comment(@stranger)
ActionMailer::Base.deliveries.count.should == 1
ActionMailer::Base.deliveries.last.to.include?(@project.owner.email).should == true
@@ -298,8 +301,7 @@ describe Comment do
context 'for committer' do
it 'should send an e-mail' do
- @simple.subscribes.destroy_all
- @simple.update_attribute :email, 'test@test.test'
+ @simple.update_column :email, 'test@test.test'
comment = create_comment(@user)
ActionMailer::Base.deliveries.count.should == 1
ActionMailer::Base.deliveries.last.to.include?(@simple.email).should == true
@@ -307,31 +309,30 @@ describe Comment do
it 'should send a one e-mail when subscribed to commit' do
Subscribe.subscribe_to_commit @subscribe_params.merge(:user_id => @simple.id)
- @simple.update_attribute :email, 'test@test.test'
+ @simple.update_column :email, 'test@test.test'
comment = create_comment(@user)
ActionMailer::Base.deliveries.count.should == 1
ActionMailer::Base.deliveries.last.to.include?(@simple.email).should == true
end
it 'should not send an e-mail for own comment' do
- @simple.subscribes.destroy_all
- @simple.update_attribute :email, 'test@test.test'
+ @simple.update_column :email, 'test@test.test'
comment = create_comment(@simple)
ActionMailer::Base.deliveries.count.should == 0
end
it 'should not send an e-mail if global notify off' do
- @project.owner.notifier.update_attribute :can_notify, false
- @simple.update_attribute :email, 'test@test.test'
- @simple.notifier.update_attribute :can_notify, false
+ @project.owner.notifier.update_column :can_notify, false
+ @simple.update_column :email, 'test@test.test'
+ @simple.notifier.update_column :can_notify, false
comment = create_comment(@user)
ActionMailer::Base.deliveries.count.should == 0
end
it 'should not send an e-mail if notify for my commits off' do
Comment.destroy_all
- @simple.notifier.update_attribute :new_comment_commit_owner, false
- @simple.update_attribute :email, 'test@test.test'
+ @simple.notifier.update_column :new_comment_commit_owner, false
+ @simple.update_column :email, 'test@test.test'
comment = create_comment(@user)
ActionMailer::Base.deliveries.count.should == 0
end
diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb
index afc99e0bc..6afc22242 100644
--- a/spec/models/comment_spec.rb
+++ b/spec/models/comment_spec.rb
@@ -84,7 +84,8 @@ describe Comment do
set_commentable_data
- @project.update_attribute(:owner, @user)
+ @project.owner = @user
+ @project.save
@project.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
end
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 36209c472..e1bede7bf 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -61,8 +61,11 @@ describe Group do
context 'for group owner' do
before(:each) do
- @user = FactoryGirl.create(:user)
- @group.update_attribute(:owner, @user)
+ @user = FactoryGirl.create(:user)
+
+ @group.owner = @user
+ @group.save
+
@group.actors.create(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
@ability = Ability.new(@user)
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index b50c1e6a4..ab13f6ae3 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
describe Project do
- before(:each) do
+ before do
stub_symlink_methods
@root_project = FactoryGirl.create(:project)
@child_project = @root_project.fork(FactoryGirl.create(:user))
@@ -10,7 +10,7 @@ describe Project do
end
context 'for destroy root' do
- before(:each) do
+ before do
@root_project.destroy
end
@@ -23,6 +23,31 @@ describe Project do
end
end
+ context 'attach personal repository' do
+ let(:user) { FactoryGirl.create(:user) }
+ it "ensures that personal repository has been attached when project had been created as package" do
+ project = FactoryGirl.create(:project, :owner => user, :is_package => true)
+ project.repositories.should == [user.personal_repository]
+ end
+
+ it "ensures that personal repository has not been attached when project had been created as not package" do
+ project = FactoryGirl.create(:project, :owner => user, :is_package => false)
+ project.repositories.should have(:no).items
+ end
+
+ it "ensures that personal repository has been attached when project had been updated as package" do
+ project = FactoryGirl.create(:project, :owner => user, :is_package => false)
+ project.update_attribute(:is_package, true)
+ project.repositories.should == [user.personal_repository]
+ end
+
+ it "ensures that personal repository has been removed from project when project had been updated as not package" do
+ project = FactoryGirl.create(:project, :owner => user, :is_package => true)
+ project.update_attribute(:is_package, false)
+ project.repositories.should have(:no).items
+ end
+ end
+
# uncommit when will be available :orphan_strategy => :adopt
#context 'for destroy middle node' do
@@ -38,4 +63,4 @@ describe Project do
# Project.where(:id => @child_child_project).count.should == 1
# end
#end
-end
\ No newline at end of file
+end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 8e61b75c6..75e39175d 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -45,7 +45,9 @@ describe User do
context 'for group project' do
before(:each) do
@project.relations.destroy_all
- @project.update_attribute :owner, @group
+
+ @project.owner = @group
+ @project.save
@project.relations.create :actor_id => @project.owner.id, :actor_type => @project.owner.class.to_s, :role => 'admin'
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index a29d72fa6..e7ce00299 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -25,6 +25,9 @@ RSpec.configure do |config|
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
+
+ config.filter_run_excluding :anonymous_access => !(APP_CONFIG['anonymous_access'])
+
end
def set_session_for(user=nil)
diff --git a/spec/support/shared_examples/projects_controller.rb b/spec/support/shared_examples/projects_controller.rb
deleted file mode 100644
index 0e4b4aff2..000000000
--- a/spec/support/shared_examples/projects_controller.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# -*- encoding : utf-8 -*-
-shared_examples_for 'projects user with reader rights' do
- include_examples 'user with rights to view projects' # nested shared_examples_for dont work
-
- it 'should be able to fork project' do
- post :fork, :owner_name => @project.owner.uname, :project_name => @project.name
- response.should redirect_to(project_path(Project.last))
- end
-
-end
-
-shared_examples_for 'projects user with admin rights' do
- it 'should be able to perform update action' do
- put :update, {:owner_name => @project.owner.uname, :project_name => @project.name}.merge(@update_params)
- response.should redirect_to(project_path(@project))
- end
-end
-
-shared_examples_for 'user with rights to view projects' do
- it 'should be able to perform index action' do
- get :index
- response.should render_template(:index)
- end
-end
-
-shared_examples_for 'user without update rights' do
- it 'should not be able to edit project' do
- description = @project.description
- put :update, :project=>{:description =>"hack"}, :owner_name => @project.owner.uname, :project_name => @project.name
- Project.find(@project.id).description.should == description
- response.should redirect_to(forbidden_path)
- end
-
- it 'should not be able to edit project sections' do
- has_wiki, has_issues = @project.has_wiki, @project.has_issues
- post :sections, :project =>{:has_wiki => !has_wiki, :has_issues => !has_issues}, :owner_name => @project.owner.uname, :project_name => @project.name
- project = Project.find(@project.id)
- project.has_wiki.should == has_wiki
- project.has_issues.should == has_issues
- response.should redirect_to(forbidden_path)
- end
-end
diff --git a/vendor/assets/javascripts/bootstrap-tab.js b/vendor/assets/javascripts/bootstrap-tab.js
index b3938f671..a26da9b6c 100644
--- a/vendor/assets/javascripts/bootstrap-tab.js
+++ b/vendor/assets/javascripts/bootstrap-tab.js
@@ -127,4 +127,4 @@
})
})
-}( window.jQuery );
\ No newline at end of file
+}( window.jQuery );
diff --git a/vendor/assets/javascripts/vendor.js b/vendor/assets/javascripts/vendor.js
index b02bf3d4a..08fc17f77 100644
--- a/vendor/assets/javascripts/vendor.js
+++ b/vendor/assets/javascripts/vendor.js
@@ -14,6 +14,7 @@
// require bootstrap-tooltip
// require bootstrap-popover
//= require bootstrap-alert
+//= require bootstrap-tab
//= require chosen.jquery
// require html5shiv
// require_tree .
diff --git a/vendor/assets/stylesheets/bootstrap.css b/vendor/assets/stylesheets/bootstrap.css
index 6f3753414..f5b1a58bc 100644
--- a/vendor/assets/stylesheets/bootstrap.css
+++ b/vendor/assets/stylesheets/bootstrap.css
@@ -422,7 +422,7 @@
}
.nav {
margin-left: 0;
- margin-bottom: 18px;
+ margin-bottom: 20px;
list-style: none;
}
.nav > li > a {
@@ -432,12 +432,15 @@
text-decoration: none;
background-color: #eeeeee;
}
-.nav .nav-header {
+.nav > .pull-right {
+ float: right;
+}
+.nav-header {
display: block;
padding: 3px 15px;
font-size: 11px;
font-weight: bold;
- line-height: 18px;
+ line-height: 20px;
color: #999999;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
text-transform: uppercase;
@@ -469,13 +472,13 @@
margin-right: 2px;
}
.nav-list .divider {
+ *width: 100%;
height: 1px;
- margin: 8px 1px;
+ margin: 9px 1px;
+ *margin: -5px 0 5px;
overflow: hidden;
background-color: #e5e5e5;
border-bottom: 1px solid #ffffff;
- *width: 100%;
- *margin: -5px 0 5px;
}
.nav-tabs,
.nav-pills {
@@ -487,6 +490,7 @@
.nav-pills:after {
display: table;
content: "";
+ line-height: 0;
}
.nav-tabs:after,
.nav-pills:after {
@@ -512,7 +516,7 @@
.nav-tabs > li > a {
padding-top: 8px;
padding-bottom: 8px;
- line-height: 18px;
+ line-height: 20px;
border: 1px solid transparent;
-webkit-border-radius: 4px 4px 0 0;
-moz-border-radius: 4px 4px 0 0;
@@ -559,14 +563,20 @@
border-radius: 0;
}
.nav-tabs.nav-stacked > li:first-child > a {
- -webkit-border-radius: 4px 4px 0 0;
- -moz-border-radius: 4px 4px 0 0;
- border-radius: 4px 4px 0 0;
+ -webkit-border-top-right-radius: 4px;
+ -moz-border-radius-topright: 4px;
+ border-top-right-radius: 4px;
+ -webkit-border-top-left-radius: 4px;
+ -moz-border-radius-topleft: 4px;
+ border-top-left-radius: 4px;
}
.nav-tabs.nav-stacked > li:last-child > a {
- -webkit-border-radius: 0 0 4px 4px;
- -moz-border-radius: 0 0 4px 4px;
- border-radius: 0 0 4px 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ -moz-border-radius-bottomright: 4px;
+ border-bottom-right-radius: 4px;
+ -webkit-border-bottom-left-radius: 4px;
+ -moz-border-radius-bottomleft: 4px;
+ border-bottom-left-radius: 4px;
}
.nav-tabs.nav-stacked > li > a:hover {
border-color: #ddd;
@@ -578,46 +588,50 @@
.nav-pills.nav-stacked > li:last-child > a {
margin-bottom: 1px;
}
-.nav-tabs .dropdown-menu,
-.nav-pills .dropdown-menu {
- margin-top: 1px;
- border-width: 1px;
+.nav-tabs .dropdown-menu {
+ -webkit-border-radius: 0 0 6px 6px;
+ -moz-border-radius: 0 0 6px 6px;
+ border-radius: 0 0 6px 6px;
}
.nav-pills .dropdown-menu {
- -webkit-border-radius: 4px;
- -moz-border-radius: 4px;
- border-radius: 4px;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
}
-.nav-tabs .dropdown-toggle .caret,
-.nav-pills .dropdown-toggle .caret {
+.nav .dropdown-toggle .caret {
border-top-color: #0088cc;
border-bottom-color: #0088cc;
margin-top: 6px;
}
-.nav-tabs .dropdown-toggle:hover .caret,
-.nav-pills .dropdown-toggle:hover .caret {
+.nav .dropdown-toggle:hover .caret {
border-top-color: #005580;
border-bottom-color: #005580;
}
-.nav-tabs .active .dropdown-toggle .caret,
-.nav-pills .active .dropdown-toggle .caret {
- border-top-color: #333333;
- border-bottom-color: #333333;
+/* move down carets for tabs */
+.nav-tabs .dropdown-toggle .caret {
+ margin-top: 8px;
+}
+.nav .active .dropdown-toggle .caret {
+ border-top-color: #fff;
+ border-bottom-color: #fff;
+}
+.nav-tabs .active .dropdown-toggle .caret {
+ border-top-color: #555555;
+ border-bottom-color: #555555;
}
.nav > .dropdown.active > a:hover {
- color: #000000;
cursor: pointer;
}
.nav-tabs .open .dropdown-toggle,
.nav-pills .open .dropdown-toggle,
-.nav > .open.active > a:hover {
+.nav > li.dropdown.open.active > a:hover {
color: #ffffff;
background-color: #999999;
border-color: #999999;
}
-.nav .open .caret,
-.nav .open.active .caret,
-.nav .open a:hover .caret {
+.nav li.dropdown.open .caret,
+.nav li.dropdown.open.active .caret,
+.nav li.dropdown.open a:hover .caret {
border-top-color: #ffffff;
border-bottom-color: #ffffff;
opacity: 1;
@@ -633,17 +647,17 @@
.tabbable:after {
display: table;
content: "";
+ line-height: 0;
}
.tabbable:after {
clear: both;
}
.tab-content {
- display: table;
- width: 100%;
+ overflow: auto;
}
-.tabs-below .nav-tabs,
-.tabs-right .nav-tabs,
-.tabs-left .nav-tabs {
+.tabs-below > .nav-tabs,
+.tabs-right > .nav-tabs,
+.tabs-left > .nav-tabs {
border-bottom: 0;
}
.tab-content > .tab-pane,
@@ -654,74 +668,83 @@
.pill-content > .active {
display: block;
}
-.tabs-below .nav-tabs {
+.tabs-below > .nav-tabs {
border-top: 1px solid #ddd;
}
-.tabs-below .nav-tabs > li {
+.tabs-below > .nav-tabs > li {
margin-top: -1px;
margin-bottom: 0;
}
-.tabs-below .nav-tabs > li > a {
+.tabs-below > .nav-tabs > li > a {
-webkit-border-radius: 0 0 4px 4px;
-moz-border-radius: 0 0 4px 4px;
border-radius: 0 0 4px 4px;
}
-.tabs-below .nav-tabs > li > a:hover {
+.tabs-below > .nav-tabs > li > a:hover {
border-bottom-color: transparent;
border-top-color: #ddd;
}
-.tabs-below .nav-tabs .active > a,
-.tabs-below .nav-tabs .active > a:hover {
+.tabs-below > .nav-tabs > .active > a,
+.tabs-below > .nav-tabs > .active > a:hover {
border-color: transparent #ddd #ddd #ddd;
}
-.tabs-left .nav-tabs > li,
-.tabs-right .nav-tabs > li {
+.tabs-left > .nav-tabs > li,
+.tabs-right > .nav-tabs > li {
float: none;
}
-.tabs-left .nav-tabs > li > a,
-.tabs-right .nav-tabs > li > a {
+.tabs-left > .nav-tabs > li > a,
+.tabs-right > .nav-tabs > li > a {
min-width: 74px;
margin-right: 0;
margin-bottom: 3px;
}
-.tabs-left .nav-tabs {
+.tabs-left > .nav-tabs {
float: left;
margin-right: 19px;
border-right: 1px solid #ddd;
}
-.tabs-left .nav-tabs > li > a {
+.tabs-left > .nav-tabs > li > a {
margin-right: -1px;
-webkit-border-radius: 4px 0 0 4px;
-moz-border-radius: 4px 0 0 4px;
border-radius: 4px 0 0 4px;
}
-.tabs-left .nav-tabs > li > a:hover {
+.tabs-left > .nav-tabs > li > a:hover {
border-color: #eeeeee #dddddd #eeeeee #eeeeee;
}
-.tabs-left .nav-tabs .active > a,
-.tabs-left .nav-tabs .active > a:hover {
+.tabs-left > .nav-tabs .active > a,
+.tabs-left > .nav-tabs .active > a:hover {
border-color: #ddd transparent #ddd #ddd;
*border-right-color: #ffffff;
}
-.tabs-right .nav-tabs {
+.tabs-right > .nav-tabs {
float: right;
margin-left: 19px;
border-left: 1px solid #ddd;
}
-.tabs-right .nav-tabs > li > a {
+.tabs-right > .nav-tabs > li > a {
margin-left: -1px;
-webkit-border-radius: 0 4px 4px 0;
-moz-border-radius: 0 4px 4px 0;
border-radius: 0 4px 4px 0;
}
-.tabs-right .nav-tabs > li > a:hover {
+.tabs-right > .nav-tabs > li > a:hover {
border-color: #eeeeee #eeeeee #eeeeee #dddddd;
}
-.tabs-right .nav-tabs .active > a,
-.tabs-right .nav-tabs .active > a:hover {
+.tabs-right > .nav-tabs .active > a,
+.tabs-right > .nav-tabs .active > a:hover {
border-color: #ddd #ddd #ddd transparent;
*border-left-color: #ffffff;
}
+.nav > .disabled > a {
+ color: #999999;
+}
+.nav > .disabled > a:hover {
+ text-decoration: none;
+ background-color: transparent;
+ cursor: default;
+}
+
.label-bootstrap,
.badge {
@@ -792,3 +815,4 @@ a.badge:hover {
.badge-inverse[href] {
background-color: #1a1a1a;
}
+