diff --git a/Gemfile b/Gemfile index fc2d4b52c..fb1f84078 100644 --- a/Gemfile +++ b/Gemfile @@ -71,6 +71,7 @@ group :development do gem 'shotgun' # deploy gem 'capistrano', :require => false + gem 'rvm-capistrano', :require => false gem 'cape', :require => false gem 'capistrano_colors', :require => false end diff --git a/Gemfile.lock b/Gemfile.lock index b886c2ac3..fda927bb5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -255,6 +255,8 @@ GEM ruby-openid (2.1.8) russian (0.6.0) i18n (>= 0.5.0) + rvm-capistrano (1.1.0) + capistrano (>= 2.0.0) sanitize (2.0.3) nokogiri (>= 1.4.4, < 1.6) sass (3.1.16) @@ -358,6 +360,7 @@ DEPENDENCIES rspec-rails (~> 2.9.0) ruby-haml-js (~> 0.0.3) russian (~> 0.6.0) + rvm-capistrano sass-rails (~> 3.2.5) shotgun shoulda diff --git a/app/assets/images/rss.ico b/app/assets/images/rss.ico new file mode 100644 index 000000000..a4ef665db Binary files /dev/null and b/app/assets/images/rss.ico differ diff --git a/app/assets/images/top-left-tour.png b/app/assets/images/top-left-tour.png new file mode 100644 index 000000000..e5fa1be74 Binary files /dev/null and b/app/assets/images/top-left-tour.png differ diff --git a/app/assets/images/top-left.png b/app/assets/images/top-left.png index 3590e4141..3e3142321 100644 Binary files a/app/assets/images/top-left.png and b/app/assets/images/top-left.png differ diff --git a/app/assets/images/top-right-tour.png b/app/assets/images/top-right-tour.png new file mode 100644 index 000000000..caa97d44c Binary files /dev/null and b/app/assets/images/top-right-tour.png differ diff --git a/app/assets/images/top-right.png b/app/assets/images/top-right.png index 8f6e2ac4c..5e6831238 100644 Binary files a/app/assets/images/top-right.png and b/app/assets/images/top-right.png differ diff --git a/app/assets/images/tour-bg.png b/app/assets/images/tour-bg.png new file mode 100644 index 000000000..723650110 Binary files /dev/null and b/app/assets/images/tour-bg.png differ diff --git a/app/assets/images/tour-top-eng.png b/app/assets/images/tour-top-eng.png new file mode 100644 index 000000000..497b2ab62 Binary files /dev/null and b/app/assets/images/tour-top-eng.png differ diff --git a/app/assets/images/tour-top.png b/app/assets/images/tour-top.png new file mode 100644 index 000000000..12aacf07f Binary files /dev/null and b/app/assets/images/tour-top.png differ diff --git a/app/assets/images/tour/annotation.png b/app/assets/images/tour/annotation.png new file mode 100644 index 000000000..89459bffd Binary files /dev/null and b/app/assets/images/tour/annotation.png differ diff --git a/app/assets/images/tour/big/annotation.png b/app/assets/images/tour/big/annotation.png new file mode 100644 index 000000000..b0926e960 Binary files /dev/null and b/app/assets/images/tour/big/annotation.png differ diff --git a/app/assets/images/tour/big/build.png b/app/assets/images/tour/big/build.png new file mode 100644 index 000000000..c9fd337ab Binary files /dev/null and b/app/assets/images/tour/big/build.png differ diff --git a/app/assets/images/tour/big/control.png b/app/assets/images/tour/big/control.png new file mode 100644 index 000000000..7c5171e21 Binary files /dev/null and b/app/assets/images/tour/big/control.png differ diff --git a/app/assets/images/tour/big/edit.png b/app/assets/images/tour/big/edit.png new file mode 100644 index 000000000..1df3d5778 Binary files /dev/null and b/app/assets/images/tour/big/edit.png differ diff --git a/app/assets/images/tour/big/git.png b/app/assets/images/tour/big/git.png new file mode 100644 index 000000000..9898b998d Binary files /dev/null and b/app/assets/images/tour/big/git.png differ diff --git a/app/assets/images/tour/big/history.png b/app/assets/images/tour/big/history.png new file mode 100644 index 000000000..b1d06f382 Binary files /dev/null and b/app/assets/images/tour/big/history.png differ diff --git a/app/assets/images/tour/big/monitoring.png b/app/assets/images/tour/big/monitoring.png new file mode 100644 index 000000000..b9357d0d7 Binary files /dev/null and b/app/assets/images/tour/big/monitoring.png differ diff --git a/app/assets/images/tour/big/repo.png b/app/assets/images/tour/big/repo.png new file mode 100644 index 000000000..f9291bd33 Binary files /dev/null and b/app/assets/images/tour/big/repo.png differ diff --git a/app/assets/images/tour/big/source.png b/app/assets/images/tour/big/source.png new file mode 100644 index 000000000..3b747ef55 Binary files /dev/null and b/app/assets/images/tour/big/source.png differ diff --git a/app/assets/images/tour/big/tracker.png b/app/assets/images/tour/big/tracker.png new file mode 100644 index 000000000..5263e4400 Binary files /dev/null and b/app/assets/images/tour/big/tracker.png differ diff --git a/app/assets/images/tour/builds.png b/app/assets/images/tour/builds.png new file mode 100644 index 000000000..1caf4c4bd Binary files /dev/null and b/app/assets/images/tour/builds.png differ diff --git a/app/assets/images/tour/control.png b/app/assets/images/tour/control.png new file mode 100644 index 000000000..54e764009 Binary files /dev/null and b/app/assets/images/tour/control.png differ diff --git a/app/assets/images/tour/edit.png b/app/assets/images/tour/edit.png new file mode 100644 index 000000000..d66c72d66 Binary files /dev/null and b/app/assets/images/tour/edit.png differ diff --git a/app/assets/images/tour/git.png b/app/assets/images/tour/git.png new file mode 100644 index 000000000..d5af3df4c Binary files /dev/null and b/app/assets/images/tour/git.png differ diff --git a/app/assets/images/tour/history.png b/app/assets/images/tour/history.png new file mode 100644 index 000000000..17b422bd4 Binary files /dev/null and b/app/assets/images/tour/history.png differ diff --git a/app/assets/images/tour/monitoring.png b/app/assets/images/tour/monitoring.png new file mode 100644 index 000000000..7e18b85d0 Binary files /dev/null and b/app/assets/images/tour/monitoring.png differ diff --git a/app/assets/images/tour/repo.png b/app/assets/images/tour/repo.png new file mode 100644 index 000000000..dae180392 Binary files /dev/null and b/app/assets/images/tour/repo.png differ diff --git a/app/assets/images/tour/source.png b/app/assets/images/tour/source.png new file mode 100644 index 000000000..4f6668fd4 Binary files /dev/null and b/app/assets/images/tour/source.png differ diff --git a/app/assets/images/tour/tracker.png b/app/assets/images/tour/tracker.png new file mode 100644 index 000000000..fafa691e9 Binary files /dev/null and b/app/assets/images/tour/tracker.png differ diff --git a/app/assets/javascripts/extra/build_list.js b/app/assets/javascripts/extra/build_list.js index 96cc24836..ef50c2b2d 100644 --- a/app/assets/javascripts/extra/build_list.js +++ b/app/assets/javascripts/extra/build_list.js @@ -1,5 +1,5 @@ $(document).ready(function() { - $('#build_list_pl_id').change(function() { + $('#build_list_save_to_platform_id').change(function() { var platform_id = $(this).val(); var base_platforms = $('.all_platforms input[type=checkbox].build_bpl_ids'); @@ -15,7 +15,7 @@ $(document).ready(function() { $(this).attr('checked', 'checked').removeAttr('disabled').trigger('change'); $(this).parent().find('.offset25 input[type="checkbox"]').removeAttr('disabled'); - var rep_name = $('#build_list_pl_id option[value="' + $(this).val() + '"]').text().match(/[\w-]+\/([\w-]+)/)[1]; + 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'); } @@ -33,7 +33,7 @@ $(document).ready(function() { setBranchSelected(); }); - $('#build_list_pl_id').trigger('change'); + $('#build_list_save_to_platform_id').trigger('change'); $('.offset25 label').click(function() { setPlChecked($(this).prev()[0], !$(this).prev().attr('checked')); @@ -58,10 +58,10 @@ function setPlChecked(pointer, checked) { } function setBranchSelected() { - var pl_id = $('#build_list_pl_id').val(); + 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_pl_id option[value="' + pl_id + '"]').text().match(/([\w-]+)\/[\w-]+/)[1]; + 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 ) { diff --git a/app/assets/javascripts/tour.js b/app/assets/javascripts/tour.js new file mode 100644 index 000000000..db3235da8 --- /dev/null +++ b/app/assets/javascripts/tour.js @@ -0,0 +1,3 @@ +//= require jquery +//= require jquery-ui +//= require pirobox_extended_min diff --git a/app/assets/stylesheets/design/custom.scss b/app/assets/stylesheets/design/custom.scss index c19b30dfc..78a929845 100644 --- a/app/assets/stylesheets/design/custom.scss +++ b/app/assets/stylesheets/design/custom.scss @@ -456,6 +456,18 @@ table.tablesorter.platforms .th2 { width: 280px; } +table.tablesorter.advisories .th1 { + width: 120px; +} + +table.tablesorter.advisories .th2 { + width: 250px; +} + +table.tablesorter.advisories .th3 { + width: auto; +} + table.tablesorter tr td.buttons { text-align: center; } @@ -922,6 +934,16 @@ div#git_help_data p { background: none repeat scroll 0 0; } -.font14 { - font-size: 14px; +.rightlist p { + padding-bottom: 1em; +} + +.leftlist span.hint { + padding-top: 1em; + display: block; + font-size: 0.9em; +} + +.atom_icon { + vertical-align: top; } diff --git a/app/assets/stylesheets/tour.scss b/app/assets/stylesheets/tour.scss new file mode 100644 index 000000000..4d1844468 --- /dev/null +++ b/app/assets/stylesheets/tour.scss @@ -0,0 +1,455 @@ +html, body { + margin: 0; + padding: 0; + font-family: Tahoma, Geneva, Helvetica, sans-serif; + color: #292929; + background: #1f60a1 image-url("bg.png") repeat-x; + min-width: 940px; + min-height: 600px; + text-align: center; + height: 100%; +} + +header, section, footer, aside, nav, article, menu { + display: block; +} + +input[type="text"]:focus { outline: none; } + +input[type="password"]:focus { outline: none; } + +input:focus { outline: none; } + +select:focus { outline: none; } + +a img { border: none; } + +.wrap { + width: 940px; + margin: 0 auto; + text-align: center; + border: 1px solid #3f668c; + -webkit-box-shadow: 0px 0px 7px 0px rgba(0, 0, 0, 0.5); + -moz-box-shadow: 0px 0px 7px 0px rgba(0, 0, 0, 0.5); + box-shadow: 0px 0px 7px 0px rgba(0, 0, 0, 0.5); + background: #FFF; + min-height: 92%; +} + + + +.both { + clear: both; +} + +/* Top menu */ + +header { + -webkit-box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.4); + -moz-box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.4); + box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.4); + position: relative; + z-index: 1000; +} + +header div.left { + background: image-url("top-left-tour.png"); + height: 46px; + width: 14px; + float: left; +} + +header div.middle { + background: image-url("top-middle.png"); + float: left; + height: 46px; + width: 912px; +} + +header div.right { + background: image-url("top-right-tour.png"); + height: 46px; + width: 14px; + float: right; +} + +/* Left part of top menu*/ + +header menu { + float: left; + margin: 0; + padding: 0; +} + +header menu ul { + list-style: none; + margin: 0; + padding-top: 10px; +} + +header menu ul li { + display: inline; +} + +header menu ul li a { + font-size: 12px; + color: #FFF; + text-decoration: none; + height: 43px; + padding: 15px 10px 15px 10px; +} + +header menu ul li a:hover { + color: #cee7ff; +} + +header menu ul li a.first { + +} + +header menu ul li a.active { + background: image-url("menu-hover.png") repeat-x; +} + + + +header div.logo { + float: left; + margin-top: 5px; + padding-left: 0px; + padding-right: 0px; + +} + +/* Right part of top menu */ + +header div.information { + float: right; +} + +header div.search { + float: left; + margin: 10px 0px 0px 0px; + -moz-border-radius-topleft: 3px; + -moz-border-radius-topright: 3px; + -moz-border-radius-bottomright: 3px; + -moz-border-radius-bottomleft: 3px; + -webkit-border-radius: 3px 3px 3px 3px; + border-radius: 3px 3px 3px 3px; + background: #FFF; + border: 1px solid #7691aa; +} + +header div.search div.pic { + background: image-url("search-button.png"); + height: 22px; + width: 24px; + float: left; +} + +header div.search div.field { + float: left; + margin: -1px 0px 0px 0px; +} + +header div.search div.field input { + border: none; + height: 18px; + background: none; + width: 132px; + font-size: 12px; + font-family: Arial; + padding: 2px 0px 0px 0px; +} + +header div.search div.field input.gray { + color: #cfcfcf; +} + +header div.search div.field input.black { + color: #333333; +} + +header div.avatar { + float:left; + padding: 6px 10px 10px 10px; + +} + +header div.information div.active { + background: image-url("menu-hover.png") repeat-x; +} + +header div.information div.user { + float: left; + margin-left: 14px; +} + +header div.profile { + float: left; + text-align: right; + color: #FFF; + font-size: 12px; + padding-top: 12px; +} + +header div.profile a { + color: #FFF; + text-decoration: none; + padding-right: 10px; +} + +header div.profile a:hover { + text-decoration: underline; +} + + +header div.droplist-wrap { + margin: -4px 0px 0px 0px; + width: 151px; + float: right; +} + +header div.droplist { + background: image-url("bg-droplist.png") repeat-x; + height: 91px; + width: 151px; + -webkit-box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5); + -moz-box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5); + box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5); + position: absolute; + margin-top: 0px; + border-radius: 0px 0px 4px 4px; + display: none; + text-align: right; + z-index: 9999; +} + +header div.droplist-wrap div.a { + margin-top: 5px; +} + +header div.droplist a{ + position: relative; + padding-left: 15px; + font-size: 12px; + color: #447cae; + text-decoration: none; + padding-right: 15px; + margin-top: 10px; +} + +header div.droplist a:hover{ + text-decoration: underline; +} + + +/* Submenu */ + +.sub-menu { + height: 38px; + margin: -7px 0px 0px 0px; + padding: 0px 0px 0px 15px; + background: #ededed; + position: relative; + z-index: 100; + border-bottom: 1px solid #FFF; + -webkit-box-shadow: 0px 5px 3px -3px rgba(18, 86, 135, 0.2); + -moz-box-shadow: 0px 5px 3px -3px rgba(18, 86, 135, 0.2); + box-shadow: 0px 5px 3px -3px rgba(18, 86, 135, 0.2); +} + +.sub-menu div.left { + float: left; + width: 200px; + border-right: 1px solid #dcdcdc; + font-size: 12px; + text-align: left; + font-weight: 700; + padding: 10px 0px 0px 0px; + height: 21px; +} + +.sub-menu div.right { + float: left; +} + + +.sub-menu nav { + float: left; + margin: 0px 0px 0px 0px; +} + +.sub-menu nav ul { + list-style: none; + text-align: left; + padding: 0; + margin: 0; + padding-top: 4px; +} + +.sub-menu nav ul li { + display: inline; +} + +.sub-menu nav ul li a { + font-size: 12px; + color: #292929; + text-decoration: none; + height: 34px; + padding: 0px 20px 9px 20px; +} + +.sub-menu nav ul li a.active { + background: image-url("submenu-hover.png") repeat-x scroll 0 100% transparent; +} + +.sub-menu nav ul li a:hover { + color: #2b6daf; +} + +/* Page markup */ + +article { + font-size: 12px; +} + +article a{ + color: #447cae; + font-size: 12px; + text-decoration: none; + padding: 0px 0px; +} + +article a:hover{ + text-decoration: underline; +} + + + +/* Footer */ + +footer { + height: 32px; + padding-left: 15px; + width: 900px; + margin: 0 auto; + text-align: center; +} + +footer ul { + margin: 0; + padding: 0; + list-style: none; + font-size: 12px; + color: #FFF; + padding-top: 10px; + text-align: left; +} + +footer ul li { + display: inline; +} + +footer ul li a { + font-size: 12px; + color: #FFF; + text-decoration: none; +} + +footer ul li a:hover { + text-decoration: underline; +} + + + +/*TOUR*/ + +header.top { + position: relative; + z-index: 3; + background: none; + background: image-url("tour-top.png") no-repeat 0 0; +} + +header.tour { + height: 194px; + position: relative; + z-index: 2; +} + +div.sub-menu.tour { + padding: 10px 0 0 0; + height: 35px; + text-align: center; + position: relative; + z-index: 1; +} + +div.sub-menu.tour nav { + float: none; +} + +div.sub-menu.tour nav ul { + text-align: center; +} + +div.sub-menu.tour nav li a { + font-size: 18px; + color: #575756; +} + +article div.feature-wrap { + background: image-url("tour-bg.png") repeat-x 0 100%; + text-align: center; + margin-top: 20px; +} + +article div.feature { + width: 744px; + text-align: center; + margin: 0 auto; +} + +article div.feature div { + width: 362px; + text-align: left; +} + +article div.feature div img{ + padding-bottom: 50px; +} + +article div.feature div h1 { + font-size: 24px; + color: #7eb7ed; + margin: -4px 0 10px 0; + padding: 0; +} + +article div.feature div p { + font-size: 12px; + color: #58595b; + padding-bottom: 50px; +} + +article div.feature div.left { + float: left; +} + +article div.feature div.right { + float: right; + padding: 0; +} + +article div.tour-gap { + height: 330px; + width: 10px; +} + +@import "pirobox"; + +/* Custom */ +header menu ul li a { + padding: 15px 8px 15px 8px; +} diff --git a/app/controllers/advisories_controller.rb b/app/controllers/advisories_controller.rb new file mode 100644 index 000000000..447a6bb5a --- /dev/null +++ b/app/controllers/advisories_controller.rb @@ -0,0 +1,19 @@ +# -*- encoding : utf-8 -*- +class AdvisoriesController < ApplicationController + before_filter :authenticate_user! + before_filter :find_advisory, :only => [:show] + load_and_authorize_resource + + def index + @advisories = @advisories.paginate(:page => params[:page]) + end + + def show + end + + protected + + def find_advisory + @advisory = Advisory.where(:advisory_id => params[:id]).limit(1).first if params[:id].present? + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b05ad486c..642ee629b 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -21,7 +21,8 @@ class ApplicationController < ActionController::Base protected def set_locale - I18n.locale = check_locale( get_user_locale || request.env['HTTP_ACCEPT_LANGUAGE'] ) + I18n.locale = check_locale( get_user_locale || + (request.env['HTTP_ACCEPT_LANGUAGE'] ? request.env['HTTP_ACCEPT_LANGUAGE'][0,2].downcase : nil )) end def get_user_locale diff --git a/app/controllers/groups/base_controller.rb b/app/controllers/groups/base_controller.rb index f40eeece2..0db3685be 100644 --- a/app/controllers/groups/base_controller.rb +++ b/app/controllers/groups/base_controller.rb @@ -6,7 +6,7 @@ class Groups::BaseController < ApplicationController protected def find_group - if group_id = params[:owner_name] || params[:group_id] || params[:id] + if group_id = params[:uname] || params[:group_id] || params[:id] @group = Group.find_by_insensitive_uname! group_id end end diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 7c06a5f96..bcb399cc5 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -4,6 +4,19 @@ class PagesController < ApplicationController # load_and_authorize_resource def root + render 'pages/tour/abf-tour-project-description-1', :layout => 'tour' + end + + def tour_inside + @entries = case params[:id] + when 'projects' + %w(repo builds monitoring) + when 'sources' + %w(source history annotation edit) + when 'builds' + %w(control git tracker) + end + render "pages/tour/tour-inside", :layout => 'tour' end def forbidden diff --git a/app/controllers/projects/build_lists_controller.rb b/app/controllers/projects/build_lists_controller.rb index 25c8e8562..d9f85ffba 100644 --- a/app/controllers/projects/build_lists_controller.rb +++ b/app/controllers/projects/build_lists_controller.rb @@ -7,7 +7,7 @@ class Projects::BuildListsController < Projects::BaseController before_filter :authenticate_build_service!, :only => CALLBACK_ACTIONS skip_before_filter :authenticate_user!, :only => [:show, :index, :search] if APP_CONFIG['anonymous_access'] - before_filter :find_build_list, :only => [:show, :publish, :cancel] + before_filter :find_build_list, :only => [:show, :publish, :cancel, :update] 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 @@ -40,16 +40,16 @@ class Projects::BuildListsController < Projects::BaseController def create notices, errors = [], [] - @platform = Platform.find params[:build_list][:pl_id] + @platform = Platform.find params[:build_list][:save_to_platform_id] params[:build_list][:auto_publish] = false if @platform.released Arch.where(:id => params[:arches]).each do |arch| - Platform.main.where(:id => params[:bpls]).each do |bpl| + Platform.main.where(:id => params[:build_for_platforms]).each do |build_for_platform| @build_list = @project.build_lists.build(params[:build_list]) @build_list.commit_hash = @project.git_repository.commits(@build_list.project_version.match(/^latest_(.+)/).to_a.last || @build_list.project_version).first.id if @build_list.project_version - @build_list.bpl = bpl; @build_list.arch = arch; @build_list.user = current_user - @build_list.include_repos = @build_list.include_repos.select {|ir| @build_list.bpl.repository_ids.include? ir.to_i} - @build_list.priority = 100 # User builds more priority than mass rebuild with zero priority - flash_options = {:project_version => @build_list.project_version, :arch => arch.name, :bpl => bpl.name, :pl => @build_list.pl} + @build_list.build_for_platform = build_for_platform; @build_list.arch = arch; @build_list.user = current_user + @build_list.include_repos = @build_list.include_repos.select {|ir| @build_list.build_for_platform.repository_ids.include? ir.to_i} + @build_list.priority = current_user.build_priority # User builds more priority than mass rebuild with zero priority + flash_options = {:project_version => @build_list.project_version, :arch => arch.name, :build_for_platform => build_for_platform.name} if @build_list.save notices << t("flash.build_list.saved", flash_options) else @@ -72,19 +72,14 @@ class Projects::BuildListsController < Projects::BaseController @item_groups = @build_list.items.group_by_level end - def publish - if @build_list.publish - redirect_to :back, :notice => t('layout.build_lists.publish_success') + def update + if params[:publish].present? and can?(:publish, @build_list) + publish + elsif params[:reject_publish].present? and can?(:reject_publish) + reject_publish else - redirect_to :back, :notice => t('layout.build_lists.publish_fail') - end - end - - def reject_publish - if @build_list.reject_publish - redirect_to :back, :notice => t('layout.build_lists.reject_publish_success') - else - redirect_to :back, :notice => t('layout.build_lists.reject_publish_fail') + # King Arthur, we are under attack! + redirect_to :forbidden and return end end @@ -117,6 +112,8 @@ class Projects::BuildListsController < Projects::BaseController @build_list.container_path = params[:container_path] @build_list.save + @build_list.set_packages(ActiveSupport::JSON.decode(params[:pkg_info])) if params[:status].to_i == BuildServer::SUCCESS and params[:pkg_info].present? + render :nothing => true, :status => 200 end @@ -172,4 +169,29 @@ class Projects::BuildListsController < Projects::BaseController render :nothing => true, :status => 403 end end + + def publish + @build_list.update_type = params[:build_list][:update_type] if params[:build_list][:update_type].present? + if params[:create_advisory].present? + a = @build_list.build_advisory + a.update_type = @build_list.update_type + a.project = @build_list.project + a.platforms << @build_list.save_to_platform unless a.platforms.include? @build_list.save_to_platform + redirect_to :back, :notice => t('layout.build_lists.publish_fail') unless a.update_attributes(params[:build_list][:advisory]) + end + if @build_list.save and @build_list.publish + redirect_to :back, :notice => t('layout.build_lists.publish_success') + else + redirect_to :back, :notice => t('layout.build_lists.publish_fail') + end + end + + def reject_publish + if @build_list.reject_publish + redirect_to :back, :notice => t('layout.build_lists.reject_publish_success') + else + redirect_to :back, :notice => t('layout.build_lists.reject_publish_fail') + end + end + end diff --git a/app/controllers/users/base_controller.rb b/app/controllers/users/base_controller.rb index 4f789e3fb..e0231bb20 100644 --- a/app/controllers/users/base_controller.rb +++ b/app/controllers/users/base_controller.rb @@ -6,7 +6,7 @@ class Users::BaseController < ApplicationController protected def find_user - if user_id = params[:owner_name] || params[:user_id] || params[:id] + if user_id = params[:uname] || params[:user_id] || params[:id] @user = User.find_by_insensitive_uname! user_id end end diff --git a/app/helpers/advisories_helper.rb b/app/helpers/advisories_helper.rb new file mode 100644 index 000000000..30d3085e8 --- /dev/null +++ b/app/helpers/advisories_helper.rb @@ -0,0 +1,12 @@ +# -*- encoding : utf-8 -*- +module AdvisoriesHelper + def construct_ref_link(ref) + ref = sanitize(ref) + url = if ref =~ %r[^http(s?)://*] + ref + else + 'http://' << ref + end + link_to url, url + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index d22a381b0..f46427676 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -17,7 +17,12 @@ module ApplicationHelper end end + def top_menu_class(base) + (controller_name.include?('build_lists') ? controller_name : params[:controller]).include?(base.to_s) ? 'active' : nil + end + def title_object object + return object.advisory_id if object.class == Advisory name = object.class == Group ? object.uname : object.name object_name = t "activerecord.models.#{object.class.name.downcase}" case object.class.name diff --git a/app/helpers/platforms_helper.rb b/app/helpers/platforms_helper.rb index fffc69c94..4ad7df6ac 100644 --- a/app/helpers/platforms_helper.rb +++ b/app/helpers/platforms_helper.rb @@ -4,10 +4,10 @@ module PlatformsHelper return "" unless platform return platform.released ? '/update' : '/release' end - - def platfrom_printed_name(platform) + + def platform_printed_name(platform) return "" unless platform platform.released? ? "#{platform.name} #{I18n.t("layout.platforms.released_suffix")}" : platform.name end - + end diff --git a/app/models/ability.rb b/app/models/ability.rb index a185daf6f..8084df6de 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -66,15 +66,18 @@ class Ability can [:read, :related], BuildList, :project => {:owner_type => 'User', :owner_id => user.id} can [:read, :related], BuildList, :project => {:owner_type => 'Group', :owner_id => user.group_ids} can(:read, BuildList, read_relations_for('build_lists', 'projects')) {|build_list| can? :read, build_list.project} - can(:create, BuildList) {|build_list| build_list.project.is_rpm && can?(:write, build_list.project)} + can([:create, :update], BuildList) {|build_list| build_list.project.is_rpm && can?(:write, build_list.project)} + can(:publish, BuildList) do |build_list| - build_list.can_publish? and build_list.pl.released ? local_admin?(build_list.pl) : can?(:write, build_list.project) + build_list.can_publish? and build_list.save_to_platform.released ? local_admin?(build_list.save_to_platform) : can?(:write, build_list.project) end can(:reject_publish, BuildList) do |build_list| - build_list.can_reject_publish? and build_list.pl.released and local_admin?(build_list.pl) + build_list.can_reject_publish? and build_list.save_to_platform.released 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 diff --git a/app/models/advisory.rb b/app/models/advisory.rb new file mode 100644 index 000000000..b9df1946b --- /dev/null +++ b/app/models/advisory.rb @@ -0,0 +1,23 @@ +class Advisory < ActiveRecord::Base + has_and_belongs_to_many :platforms + has_many :build_lists + belongs_to :project + + validates :description, :update_type, :presence => true + + after_create :generate_advisory_id + + ID_TEMPLATE = 'ROSA%s-%d:%04d' + TYPES = {'security' => 'SA', 'bugfix' => 'A'} + + def to_param + advisory_id + end + + protected + + def generate_advisory_id + self.advisory_id = sprintf(ID_TEMPLATE, :type => TYPES[self.update_type], :year => Time.now.utc.year, :id => self.id) + self.save + end +end diff --git a/app/models/build_list.rb b/app/models/build_list.rb index 38fb4111b..d96c88f6e 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -2,20 +2,28 @@ class BuildList < ActiveRecord::Base belongs_to :project belongs_to :arch - belongs_to :pl, :class_name => 'Platform' - belongs_to :bpl, :class_name => 'Platform' + belongs_to :save_to_platform, :class_name => 'Platform' + belongs_to :build_for_platform, :class_name => 'Platform' belongs_to :user + belongs_to :advisory has_many :items, :class_name => "BuildList::Item", :dependent => :destroy + has_many :packages, :class_name => "BuildList::Package", :dependent => :destroy + + UPDATE_TYPES = %w[security bugfix enhancement recommended newpackage] + RELEASE_UPDATE_TYPES = %w[security bugfix] validates :project_id, :project_version, :arch, :include_repos, :presence => true validates_numericality_of :priority, :greater_than_or_equal_to => 0 - - UPDATE_TYPES = %w[security bugfix enhancement recommended newpackage] - validates :update_type, :inclusion => UPDATE_TYPES + validates :update_type, :inclusion => UPDATE_TYPES, + :unless => Proc.new { |b| b.save_to_platform.released } + validates :update_type, :inclusion => RELEASE_UPDATE_TYPES, + :if => Proc.new { |b| b.save_to_platform.released } validate lambda { - errors.add(:bpl, I18n.t('flash.build_list.wrong_platform')) if pl.platform_type == 'main' && pl_id != bpl_id + errors.add(:build_for_platform, I18n.t('flash.build_list.wrong_platform')) if save_to_platform.platform_type == 'main' && save_to_platform_id != build_for_platform_id } + LIVE_TIME = 3.week + # The kernel does not send these statuses directly BUILD_CANCELED = 5000 WAITING_FOR_RESPONSE = 4000 @@ -62,7 +70,6 @@ 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 :scoped_to_arch, lambda {|arch| where(:arch_id => arch) } @@ -81,10 +88,11 @@ class BuildList < ActiveRecord::Base s } scope :scoped_to_project_name, lambda {|project_name| joins(:project).where('projects.name LIKE ?', "%#{project_name}%")} + scope :outdated, where('updated_at < ? AND status <> ?', Time.now - LIVE_TIME, BUILD_PUBLISHED) serialize :additional_repos serialize :include_repos - + before_create :set_default_status after_create :place_build @@ -106,6 +114,13 @@ class BuildList < ActiveRecord::Base end end + def set_packages(pkg_hash) + build_package(pkg_hash['srpm'], 'source') {|p| p.save!} + pkg_hash['rpm'].each do |rpm_hash| + build_package(rpm_hash, 'binary') {|p| p.save!} + end + end + def publish return false unless can_publish? has_published = BuildServer.publish_container bs_id @@ -123,7 +138,7 @@ class BuildList < ActiveRecord::Base end def can_reject_publish? - can_publish? and pl.released + can_publish? and save_to_platform.released end def cancel @@ -159,18 +174,26 @@ class BuildList < ActiveRecord::Base #[WAITING_FOR_RESPONSE, BuildServer::BUILD_PENDING, BuildServer::BUILD_STARTED].include?(status) end - private - def set_default_status - self.status = WAITING_FOR_RESPONSE unless self.status.present? - return true - end + protected - def place_build - #XML-RPC params: project_name, project_version, plname, arch, bplname, update_type, build_requires, id_web, include_repos, priority - self.status = BuildServer.add_build_list project.name, project_version, pl.name, arch.name, (pl_id == bpl_id ? '' : bpl.name), update_type, build_requires, id, include_repos, priority - self.status = BUILD_PENDING if self.status == 0 - save - end - #handle_asynchronously :place_build + def set_default_status + self.status = WAITING_FOR_RESPONSE unless self.status.present? + return true + end + def place_build + #XML-RPC params: project_name, project_version, plname, arch, bplname, update_type, build_requires, id_web, include_repos, priority + self.status = BuildServer.add_build_list project.name, project_version, save_to_platform.name, arch.name, (save_to_platform_id == build_for_platform_id ? '' : build_for_platform.name), update_type, build_requires, id, include_repos, priority + self.status = BUILD_PENDING if self.status == 0 + save + end + + def build_package(pkg_hash, package_type) + packages.create(pkg_hash) do |p| + p.project = project # Project.joins(:repositories => :platform).where('platforms.id = ?', save_to_platform.id).find_by_name!(pkg_hash['name']) + p.platform = save_to_platform + p.package_type = package_type + yield p + end + end end diff --git a/app/models/build_list/package.rb b/app/models/build_list/package.rb new file mode 100644 index 000000000..b491c0d13 --- /dev/null +++ b/app/models/build_list/package.rb @@ -0,0 +1,12 @@ +class BuildList::Package < ActiveRecord::Base + PACKAGE_TYPES = %w(source binary) + + belongs_to :build_list + belongs_to :project + belongs_to :platform + + attr_accessible :fullname, :name, :release, :version + + validates :build_list_id, :project_id, :platform_id, :fullname, :package_type, :name, :release, :version, :presence => true + validates :package_type, :inclusion => PACKAGE_TYPES +end diff --git a/app/models/collaborator.rb b/app/models/collaborator.rb index c0b0e35af..8b1f1b412 100644 --- a/app/models/collaborator.rb +++ b/app/models/collaborator.rb @@ -4,7 +4,7 @@ class Collaborator include ActiveModel::Validations include ActiveModel::Serializers::JSON include ActiveModel::MassAssignmentSecurity - extend ActiveModel::Naming + extend ActiveModel::Naming attr_accessor :role, :actor, :project, :relation attr_reader :id, :actor_id, :actor_type, :actor_name, :project_id diff --git a/app/models/platform.rb b/app/models/platform.rb index 826537d36..4a19de176 100644 --- a/app/models/platform.rb +++ b/app/models/platform.rb @@ -13,6 +13,10 @@ class Platform < ActiveRecord::Base has_many :actors, :as => :target, :class_name => 'Relation', :dependent => :destroy has_many :members, :through => :actors, :source => :actor, :source_type => 'User' + has_and_belongs_to_many :advisories + + has_many :packages, :class_name => "BuildList::Package", :dependent => :destroy + validates :description, :presence => true validates :visibility, :presence => true, :inclusion => {:in => VISIBILITIES} validates :name, :uniqueness => {:case_sensitive => false}, :presence => true, :format => { :with => /^[a-zA-Z0-9_\-]+$/ } @@ -21,11 +25,12 @@ class Platform < ActiveRecord::Base before_create :create_directory, :if => lambda {Thread.current[:skip]} # TODO remove this when core will be ready before_create :xml_rpc_create, :unless => lambda {Thread.current[:skip]} before_destroy :xml_rpc_destroy - + after_update :freeze_platform - - after_create lambda { mount_directory_for_rsync unless hidden? } - after_destroy lambda { umount_directory_for_rsync unless hidden? } + + 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") @@ -42,7 +47,7 @@ class Platform < ActiveRecord::Base include Modules::Models::Owner def urpmi_list(host, pair = nil) - blank_pair = {:login => 'login', :pass => 'password'} + blank_pair = {:login => 'login', :pass => 'password'} pair = blank_pair if pair.blank? urpmi_commands = ActiveSupport::OrderedHash.new @@ -63,7 +68,7 @@ class Platform < ActiveRecord::Base build_path(name) end - def mount_path + def symlink_path Rails.root.join("public", "downloads", name) end @@ -115,14 +120,14 @@ class Platform < ActiveRecord::Base with_skip {c.save} and c.clone_relations(self) and c.delay.xml_rpc_clone end end - + def change_visibility if !self.hidden? self.update_attribute(:visibility, 'hidden') - umount_directory_for_rsync + remove_symlink_directory else self.update_attribute(:visibility, 'open') - mount_directory_for_rsync + symlink_directory end end @@ -130,19 +135,17 @@ class Platform < ActiveRecord::Base system("sudo mkdir -p -m 0777 #{path}") end - def mount_directory_for_rsync + def symlink_directory # umount_directory_for_rsync # TODO ignore errors - system("sudo mkdir -p -m 0777 #{mount_path}") - system("sudo mount --bind #{path} #{mount_path}") + system("ln -s #{path} #{symlink_path}") Arch.all.each do |arch| str = "country=Russian Federation,city=Moscow,latitude=52.18,longitude=48.88,bw=1GB,version=2011,arch=#{arch.name},type=distrib,url=#{public_downloads_url}\n" - File.open(File.join(mount_path, "#{name}.#{arch.name}.list"), 'w') {|f| f.write(str) } + File.open(File.join(symlink_path, "#{name}.#{arch.name}.list"), 'w') {|f| f.write(str) } end end - def umount_directory_for_rsync - system("sudo umount #{mount_path}") - system("sudo rm -Rf #{mount_path}") + def remove_symlink_directory + system("rm -Rf #{symlink_path}") end def update_owner_relation @@ -210,6 +213,6 @@ class Platform < ActiveRecord::Base if released_changed? && released == true result = BuildServer.freeze(name) raise "Failed freeze platform #{name} with code #{result}" if result != BuildServer::SUCCESS - end + end end end diff --git a/app/models/project.rb b/app/models/project.rb index 4626d1b1a..08433cb8c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -2,6 +2,7 @@ class Project < ActiveRecord::Base VISIBILITIES = ['open', 'hidden'] MAX_OWN_PROJECTS = 32000 + NAME_REGEXP = /[a-zA-Z0-9_\-\+\.]+/ belongs_to :owner, :polymorphic => true, :counter_cache => :own_projects_count @@ -18,7 +19,10 @@ class Project < ActiveRecord::Base has_many :collaborators, :through => :relations, :source => :actor, :source_type => 'User' has_many :groups, :through => :relations, :source => :actor, :source_type => 'Group' - validates :name, :uniqueness => {:scope => [:owner_id, :owner_type], :case_sensitive => false}, :presence => true, :format => {:with => /^[a-zA-Z0-9_\-\+\.]+$/} + has_many :advisories # should be without :dependent => :destroy + has_many :packages, :class_name => "BuildList::Package", :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 :owner, :presence => true validate { errors.add(:base, :can_have_less_or_equal, :count => MAX_OWN_PROJECTS) if owner.projects.size >= MAX_OWN_PROJECTS } @@ -77,8 +81,8 @@ class Project < ActiveRecord::Base arch = Arch.find_by_name(arch) if arch.acts_like?(:string) build_lists.create do |bl| - bl.pl = platform - bl.bpl = platform + bl.save_to_platform = platform + bl.build_to_platform = platform bl.update_type = 'newpackage' bl.arch = arch bl.project_version = "latest_#{platform.name}" diff --git a/app/views/activity_feeds/index.html.haml b/app/views/activity_feeds/index.html.haml index f7ee1c901..a8bdf4758 100644 --- a/app/views/activity_feeds/index.html.haml +++ b/app/views/activity_feeds/index.html.haml @@ -1,5 +1,7 @@ -set_meta_tags :title => nil -%h3.fix= t("layout.activity_feed.header") +%h3.fix + = t("layout.activity_feed.header") + = link_to image_tag("rss.ico", :width => '15px', :height => '15px', :class => 'atom_icon'), atom_activity_feeds_path(:format => 'atom', :token => current_user.authentication_token) =render 'list' - content_for :sidebar, render('sidebar') diff --git a/app/views/advisories/_form.html.haml b/app/views/advisories/_form.html.haml new file mode 100644 index 000000000..a21ff2acb --- /dev/null +++ b/app/views/advisories/_form.html.haml @@ -0,0 +1,15 @@ +%h3= t("layout.advisories.form_header") + +.leftlist + = f.label :description, t("activerecord.attributes.advisory.description") +.rightlist + = f.text_area :description, :class => 'text_field', :cols => 80 +.both + +.leftlist + = f.label :references, t("activerecord.attributes.advisory.references") + %span.hint + = t("layout.advisories.ref_comment") +.rightlist + = f.text_area :references, :class => 'text_field', :cols => 80 +.both diff --git a/app/views/advisories/_list.html.haml b/app/views/advisories/_list.html.haml new file mode 100644 index 000000000..b6d80ebc9 --- /dev/null +++ b/app/views/advisories/_list.html.haml @@ -0,0 +1,8 @@ +%table#myTable.tablesorter.advisories{:cellspacing => "0", :cellpadding => "0"} + %thead + %tr + %th.th1= t("activerecord.attributes.advisory.advisory_id") + %th.th2= t("layout.advisories.affected_versions") + %th.th3= t("activerecord.attributes.advisory.description") + %tbody + = render :partial => 'list_item', :collection => list, :as => :advisory diff --git a/app/views/advisories/_list_item.html.haml b/app/views/advisories/_list_item.html.haml new file mode 100644 index 000000000..21486904f --- /dev/null +++ b/app/views/advisories/_list_item.html.haml @@ -0,0 +1,7 @@ +%tr{:class => cycle("odd", "even")} + %td= link_to advisory.advisory_id, advisory_path(advisory) + %td + - advisory.platforms.each do |platform| + = link_to platform_printed_name(platform), platform_path(platform) + %br + %td= truncate(advisory.description, :length => 50) diff --git a/app/views/advisories/_submenu.html.haml b/app/views/advisories/_submenu.html.haml new file mode 100644 index 000000000..00ad6e3cc --- /dev/null +++ b/app/views/advisories/_submenu.html.haml @@ -0,0 +1,7 @@ +- content_for :submenu do + - act = action_name.to_sym; contr = controller_name.to_sym + .left + = @advisory.advisory_id if @advisory.present? + %nav + %ul + %li= link_to t('layout.list'), advisories_path, :class => act.in?([:index]) ? 'active' : nil diff --git a/app/views/advisories/index.html.haml b/app/views/advisories/index.html.haml new file mode 100644 index 000000000..431a3e919 --- /dev/null +++ b/app/views/advisories/index.html.haml @@ -0,0 +1,4 @@ +- set_meta_tags :title => t('layout.advisories.list_header') +- render :partial => 'submenu' += render :partial => 'list', :object => @advisories += will_paginate @advisories diff --git a/app/views/advisories/show.html.haml b/app/views/advisories/show.html.haml new file mode 100644 index 000000000..483ba81a9 --- /dev/null +++ b/app/views/advisories/show.html.haml @@ -0,0 +1,37 @@ +- set_meta_tags :title => [title_object(@advisory), t('activerecord.models.advisory')] +- render :partial => 'submenu' + +%h3= "#{t("activerecord.models.advisory")} #{@advisory.advisory_id}".html_safe + +.leftlist= "#{t("layout.advisories.project_name")}:".html_safe +.rightlist= link_to @advisory.project.name, project_path(@advisory.project) +.both + +.leftlist= "#{t("activerecord.attributes.advisory.created_at")}:".html_safe +.rightlist= @advisory.created_at +.both + +.leftlist= "#{t("activerecord.attributes.advisory.advisory_id")}:".html_safe +.rightlist= @advisory.advisory_id +.both + +.leftlist= "#{t("layout.advisories.affected_versions")}:".html_safe +.rightlist + - @advisory.platforms.each do |platform| + = link_to platform_printed_name(platform), platform_path(platform) + %br +.both + +.leftlist= "#{t("activerecord.attributes.advisory.description")}:".html_safe +.rightlist= simple_format @advisory.description +.both + +.leftlist= "#{t("activerecord.attributes.advisory.references")}:".html_safe +.rightlist + - @advisory.references.gsub(/\r| /, '').split("\n").each do |ref| + = construct_ref_link(ref) + %br +.both + +:javascript + $('article .all').addClass('bigpadding'); diff --git a/app/views/groups/profile/edit.html.haml b/app/views/groups/profile/edit.html.haml index fca9df91c..e4846961f 100644 --- a/app/views/groups/profile/edit.html.haml +++ b/app/views/groups/profile/edit.html.haml @@ -1,5 +1,5 @@ -set_meta_tags :title => [title_object(@group), t('layout.groups.edit')] -= form_for @group do |f| += form_for @group, :url => profile_group_path(@group) do |f| = render "form", :f => f .hr @@ -9,7 +9,7 @@ .hr .leftside= t("layout.groups.delete_warning") .rightside - = link_to t("layout.delete"), group_path(@group), :method => :delete, :confirm => t("layout.groups.confirm_delete"), :class => 'button' if can? :destroy, @group + = link_to t("layout.delete"), profile_group_path(@group), :method => :delete, :confirm => t("layout.groups.confirm_delete"), :class => 'button' if can? :destroy, @group .both - content_for :sidebar, render('sidebar') diff --git a/app/views/layouts/menu/_top.html.haml b/app/views/layouts/menu/_top.html.haml index 552c34fa0..e5ed2e1c0 100644 --- a/app/views/layouts/menu/_top.html.haml +++ b/app/views/layouts/menu/_top.html.haml @@ -2,6 +2,6 @@ %ul - (collection = t which_menu).each do |base, title| - if can? :index, base.to_s.classify.constantize - %li= link_to title, send(:"#{namespace}#{base}_path"), :class => params[:controller].include?(base.to_s) ? 'active' : '' + %li= link_to title, send(:"#{namespace}#{base}_path"), :class => top_menu_class(base) - if current_user.try(:admin?) and which_menu == 'top_menu' - %li= link_to t('admins_menu_header'), admin_users_path, :class => t('admins_menu').has_key?(controller_name.to_sym) ? 'active' : '' + %li= link_to t('admins_menu_header'), admin_users_path, :class => top_menu_class('admin') diff --git a/app/views/layouts/tour.html.haml b/app/views/layouts/tour.html.haml new file mode 100644 index 000000000..1f0a486bc --- /dev/null +++ b/app/views/layouts/tour.html.haml @@ -0,0 +1,58 @@ +!!! +%html + %head + %meta{:content => "text/html; charset=utf-8", "http-equiv" => "Content-Type"}/ + %title Сборочная среда + = stylesheet_link_tag "tour" + /[if lt IE 9] + = javascript_include_tag 'https://html5shiv.googlecode.com/svn/trunk/html5.js' + = javascript_include_tag "tour" + = csrf_meta_tag + %body + .wrap + %header.top + .left + .middle + %menu + .logo= link_to image_tag('logo-mini.png', :alt => 'logo'), root_path + = render 'layouts/menu/top', :which_menu => 'top_menu' + .information + = render 'search/form' + - if current_user + .user + .avatar= image_tag avatar_url(current_user), :alt => 'avatar', :height => "30" + .profile + %a{:href => "#"} + = current_user.uname + = image_tag 'expand-white.png', :alt => 'ex' + .both + .both + .droplist-wrap + #droplist.droplist + .a= link_to current_user.uname, current_user + .a= link_to t('layout.settings.label'), profile_settings_path + .a= link_to t('layout.logout'), destroy_user_session_path, :method => :delete + - else + .user + .profile= link_to t("layout.devise.shared_links.sign_in"), new_user_session_path + .right + .both + / Page + .tour + =image_tag "tour-top#{I18n.locale == :en ? '-eng' : ''}.png", :alt => 'ABF' + .both + %article + = yield + .both + -# No idea why here was this div... + -#.tour-gap + %footer= render "layouts/menu/bottom" + = render 'layouts/counters' unless current_user.try(:admin?) + :javascript + $(document).ready(function() { + $().piroBox_ext({ + piro_speed : 700, + 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/pages/tour/_entry.html.haml b/app/views/pages/tour/_entry.html.haml new file mode 100644 index 000000000..c1bb10011 --- /dev/null +++ b/app/views/pages/tour/_entry.html.haml @@ -0,0 +1,19 @@ +.feature-wrap + .feature + -if is_left + .left + %h1=t "tour.#{entry}" + %p + =raw t "tour.#{entry}_description" + .right + %a.pirobox{:href => image_path("tour/big/#{entry}.png"), :rel => "single", :title => t("tour.#{entry}")} + =image_tag "tour/#{entry}.png" + -else + .left + %a.pirobox{:href => image_path("tour/big/#{entry}.png"), :rel => "single", :title => t("tour.#{entry}")} + =image_tag "tour/#{entry}.png" + .right + %h1=t "tour.#{entry}" + %p + =raw t "tour.#{entry}_description" + .both diff --git a/app/views/pages/tour/_submenu.html.haml b/app/views/pages/tour/_submenu.html.haml new file mode 100644 index 000000000..057944464 --- /dev/null +++ b/app/views/pages/tour/_submenu.html.haml @@ -0,0 +1,4 @@ +%ul + -%w(projects sources builds).each do |entry| + %li + =link_to t("tour.#{entry}"), tour_inside_path(entry), :class => params[:id] == entry ? 'active' : '' diff --git a/app/views/pages/tour/abf-tour-project-description-1.html.haml b/app/views/pages/tour/abf-tour-project-description-1.html.haml new file mode 100644 index 000000000..f74145da7 --- /dev/null +++ b/app/views/pages/tour/abf-tour-project-description-1.html.haml @@ -0,0 +1,39 @@ +.feature-wrap + .feature + .left + %a.pirobox{:href => image_path('tour/big/control.png'), :rel => "single", :title => t('tour.projects')} + =image_tag 'tour/control.png' + .right + %a{:href => tour_inside_path('projects')} + %h1=t 'tour.projects' + %p + =t 'tour.projects_header' + %br + =link_to t('tour.read_more'), tour_inside_path('projects') + .both +.feature-wrap + .feature + .left + %a{:href => tour_inside_path('sources')} + %h1=t 'tour.sources' + %p + =t 'tour.sources_header' + %br/ + =link_to t('tour.read_more'), tour_inside_path('sources') + .right + %a.pirobox{:href => image_path('tour/big/source.png'), :rel => "single", :title => t('tour.sources')} + =image_tag 'tour/source.png' + .both +.feature-wrap + .feature + .left + %a.pirobox{:href => image_path('tour/big/monitoring.png'), :rel => "single", :title => t('tour.builds')} + =image_tag 'tour/monitoring.png' + .right + %a{:href => tour_inside_path('builds')} + %h1=t 'tour.builds' + %p + =t 'tour.builds_header' + %br/ + =link_to t('tour.read_more'), tour_inside_path('builds') + .both diff --git a/app/views/pages/tour/tour-inside-sources.html.haml b/app/views/pages/tour/tour-inside-sources.html.haml new file mode 100644 index 000000000..02c225938 --- /dev/null +++ b/app/views/pages/tour/tour-inside-sources.html.haml @@ -0,0 +1,65 @@ +.sub-menu.tour + %nav + %ul + %li + =link_to 'Управление проектами', tour_inside_path('projects') + %li + =link_to 'Исходный код', tour_inside_path('sources'), :class => 'active' + %li + =link_to 'Сборка проектов', tour_inside_path('builds') +.both +/ Page +%article + / Single page content + .feature-wrap + .feature + .left + %a.pirobox{:href => image_path('tour/big/source.png'), :rel => "single", :title => "Исходный код онлайн"} + =image_tag 'tour/2/source.png' + .right + %h1 Исходный код онлайн + %p + Мы сфокусировались на том, чтобы сделать исходный код + доступным и прозрачным. Все, что вы выложите в git-репозиторий, + мгновенно станет доступным для просмотра в режиме онлайн, + чтобы вы могли поделиться им с людьми, даже если они не + используют Git. На главной странице каждого проекта есть список + файлов проекта, а также информация о последнем изменении. + Вы можете сразу увидеть самое важное в вашем проекте: код. + .both + .feature-wrap + .feature + .left + %h1 История файла + %p + Каждый файл в git-репозитории имеет историю, которую вы + легко можете посмотреть: кто, когда и что в нем поменял. + .right + %a.pirobox{:href => image_path('tour/big/history.png'), :rel => "single", :title => "История файла"} + =image_tag 'tour/2/history.png' + .both + .feature-wrap + .feature + .left + %a.pirobox{:href => image_path('tour/big/annotation.png'), :rel => "single", :title => "Аннотация файла"} + =image_tag 'tour/2/annotation.png' + .right + %h1 Аннотация файла + %p + Ищете автора фрагмента кода? Откройте аннотацию файла + (Blame), чтобы увидеть: кто и в каком коммите последний + изменял данный фрагмент. + .both + .feature-wrap + .feature + .left + %h1 Редактирования онлайн + %p + Вам нужно быстро внести изменение в файл? Исправить + орфографические ошибки на вашем мобильном телефоне? + Мы предлагаем простой редактор для каждого файла в + git-репозитории. + .right + %a.pirobox{:href => image_path('tour/big/edit.png'), :rel => "single", :title => "Редактирования онлайн"} + =image_tag 'tour/2/edit.png' + .both diff --git a/app/views/pages/tour/tour-inside.html.haml b/app/views/pages/tour/tour-inside.html.haml new file mode 100644 index 000000000..308533de4 --- /dev/null +++ b/app/views/pages/tour/tour-inside.html.haml @@ -0,0 +1,9 @@ +.sub-menu.tour + %nav + =render 'pages/tour/submenu' +.both +/ Page +%article + / Single page content + -@entries.each_with_index do |el, ind| + =render :partial => 'pages/tour/entry', :locals => {:entry => el, :is_left => ind.odd?} diff --git a/app/views/platforms/base/_submenu.html.haml b/app/views/platforms/base/_submenu.html.haml index 002546ebf..072971af2 100644 --- a/app/views/platforms/base/_submenu.html.haml +++ b/app/views/platforms/base/_submenu.html.haml @@ -1,5 +1,5 @@ - content_for :submenu do - act = action_name.to_sym; contr = controller_name.to_sym - .left= platfrom_printed_name(@platform) + .left= platform_printed_name(@platform) %nav %ul diff --git a/app/views/platforms/platforms/_list.html.haml b/app/views/platforms/platforms/_list.html.haml index b146945a7..1ac3c3353 100644 --- a/app/views/platforms/platforms/_list.html.haml +++ b/app/views/platforms/platforms/_list.html.haml @@ -6,5 +6,5 @@ %tbody - @platforms.each do |platform| %tr{:class => cycle("odd", "even")} - %td= link_to platfrom_printed_name(platform), platform_path(platform) - %td= platform.distrib_type \ No newline at end of file + %td= link_to platform_printed_name(platform), platform_path(platform) + %td= platform.distrib_type diff --git a/app/views/projects/build_lists/_include_repos.html.haml b/app/views/projects/build_lists/_include_repos.html.haml index 372d3865a..11ef89f97 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}", :pl_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}", :save_to_platform_id => platform.id, :rep_name => repo.name = label_tag "include_repos_#{repo.id}", repo.name diff --git a/app/views/projects/build_lists/new.html.haml b/app/views/projects/build_lists/new.html.haml index 9bd2464b7..10024025a 100644 --- a/app/views/projects/build_lists/new.html.haml +++ b/app/views/projects/build_lists/new.html.haml @@ -1,18 +1,17 @@ -set_meta_tags :title => [title_object(@project), t('layout.build_lists.new_header')] = form_for [@project, @build_list], :html => { :class => :form, :method => :post } do |f| %section.left - %h3= t("activerecord.attributes.build_list.bpl") + %h3= t("activerecord.attributes.build_list.build_for_platform") .all_platforms - Platform.main.each do |pl| - if pl.repository_ids.size > 0 .both - = check_box_tag "bpls[]", pl.id, (params[:bpls]||[]).include?(pl.id.to_s), :class => 'build_bpl_ids', :id => "bpls_#{pl.id}", :'data-released' => pl.released ? 1 : 0 + = 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 + .offset25{:style => 'padding-left: 25px'}= render 'include_repos', :platform => pl %section.right - %h3= t("activerecord.attributes.build_list.pl") - .lineForm= f.select :pl_id, @project.repositories.collect{|r| ["#{r.platform.name}/#{r.name}", r.platform.id]} + %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.project_version") - if controller.action_name == 'new' .lineForm= f.select :project_version, @project.versions_for_group_select, :selected => "latest_" + @project.default_branch @@ -21,10 +20,7 @@ %h3= t("activerecord.attributes.build_list.arch") - Arch.recent.each do |arch| .both - - if controller.action_name == 'new' - = check_box_tag "arches[]", arch.id, (params[:arches]||[]).include?(arch.id.to_s), :id => "arches_#{arch.id}", :checked => 'checked' - - else - = check_box_tag "arches[]", arch.id, (params[:arches]||[]).include?(arch.id.to_s), :id => "arches_#{arch.id}" + = check_box_tag "arches[]", arch.id, (params[:arches]||[]).include?(arch.id.to_s) || controller.action_name == 'new', :id => "arches_#{arch.id}" = label_tag "arches_#{arch.id}", arch.name %h3= t("activerecord.attributes.build_list.update_type") .lineForm= f.select :update_type, BuildList::UPDATE_TYPES diff --git a/app/views/projects/build_lists/show.html.haml b/app/views/projects/build_lists/show.html.haml index f5793b252..46b7b761f 100644 --- a/app/views/projects/build_lists/show.html.haml +++ b/app/views/projects/build_lists/show.html.haml @@ -4,66 +4,82 @@ %p= @build_list.human_status %p= @build_list.updated_at .both -%h3= t("layout.build_lists.main_data") -.leftside.width125= t("activerecord.attributes.build_list.container_path") -.leftside - - if @build_list.status == BuildList::BUILD_PUBLISHED - = t("layout.build_lists.container_published") - - 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 -.leftside.width125= t("activerecord.attributes.build_list.user") -.leftside - = link_to @build_list.user.try(:fullname), @build_list.user -.both -= link_to t("layout.publish"), publish_build_list_path(@build_list), :method => "put", :confirm => t("layout.confirm"), :class => "button tmargin10" if @build_list.can_publish? and can?(:publish, @build_list) -= link_to t("layout.reject_publish"), reject_publish_build_list_path(@build_list), :method => "put", :confirm => t("layout.confirm"), :class => "button tmargin10" if @build_list.can_reject_publish? and can?(:reject_publish, @build_list) -.hr -%h3= t("layout.build_lists.main_data") -.leftside.width125= t("activerecord.attributes.build_list.bpl") -.leftside - = link_to @build_list.bpl.name, @build_list.bpl -.both -.leftside.width125= t("activerecord.attributes.build_list.pl") -.leftside - = link_to @build_list.pl.name, @build_list.pl -.both -.leftside.width125= t("activerecord.attributes.build_list.include_repos") -.leftside= (@build_list.include_repos||[]).map{|r| Repository.find(r).name}.join(', ') -.both -.leftside.width125= t("activerecord.attributes.build_list.update_type") -.leftside= @build_list.update_type -.both -.leftside.width125= t("activerecord.attributes.build_list.build_requires") -.leftside= @build_list.build_requires -.both -.leftside.width125= t("activerecord.attributes.build_list.auto_publish") -.leftside= @build_list.auto_publish -.both -.leftside.width125= t("activerecord.attributes.build_list.project_version") -.leftside= @build_list.project_version -.both -.leftside.width125= t("activerecord.attributes.build_list.arch") -.leftside= @build_list.arch.name -.both -.leftside.width125= t("activerecord.attributes.build_list.updated_at") -.leftside= @build_list.updated_at -.both -.leftside.width125= t("activerecord.attributes.build_list.is_circle") -.leftside= t("layout.#{@build_list.is_circle?}_") -.both -- if !@build_list.in_work? && @build_list.started_at - %br - .leftside.width125 - .leftside= @build_list.human_duration += form_for @build_list do |f| + %h3= t("layout.build_lists.main_data") + .leftlist= t("activerecord.attributes.build_list.container_path") + .rightlist + - if @build_list.status == BuildList::BUILD_PUBLISHED + = t("layout.build_lists.container_published") + - 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 -- if @build_list.in_work? - %br - .leftside.width125 - .leftside - = "#{@build_list.human_current_duration} / #{@build_list.project.human_average_build_time}" + .leftlist= t("activerecord.attributes.build_list.user") + .rightlist + = link_to @build_list.user.try(:fullname), @build_list.user .both + .leftlist= t("activerecord.attributes.build_list.build_for_platform") + .rightlist + = link_to @build_list.build_for_platform.name, @build_list.build_for_platform + .both + .leftlist= t("activerecord.attributes.build_list.save_to_platform") + .rightlist + = link_to @build_list.save_to_platform.name, @build_list.save_to_platform + .both + .leftlist= t("activerecord.attributes.build_list.include_repos") + .rightlist= (@build_list.include_repos||[]).map{|r| Repository.find(r).name}.join(', ') + .both + .leftlist= t("activerecord.attributes.build_list.update_type") + .rightlist + - if @build_list.can_publish? and can?(:publish, @build_list) + = f.select :update_type, options_for_select(BuildList::RELEASE_UPDATE_TYPES, @build_list.update_type) + - else + = @build_list.update_type + .both + .leftlist= t("activerecord.attributes.build_list.build_requires") + .rightlist= t("layout.#{@build_list.build_requires}_") + .both + .leftlist= t("activerecord.attributes.build_list.auto_publish") + .rightlist= t("layout.#{@build_list.auto_publish}_") + .both + .leftlist= t("activerecord.attributes.build_list.project_version") + .rightlist= @build_list.project_version + .both + .leftlist= t("activerecord.attributes.build_list.arch") + .rightlist= @build_list.arch.name + .both + .leftlist= t("activerecord.attributes.build_list.updated_at") + .rightlist= @build_list.updated_at + .both + .leftlist= t("activerecord.attributes.build_list.is_circle") + .rightlist= t("layout.#{@build_list.is_circle?}_") + .both + + - if @build_list.advisory.present? + .leftlist= t("layout.build_lists.attached_advisory") + .rightlist= link_to @build_list.advisory.advisory_id, advisory_path(@build_list.advisory) + .both + - if !@build_list.in_work? && @build_list.started_at + %br + .leftlist + .rightlist= @build_list.human_duration + .both + - if @build_list.in_work? + %br + .leftlist + .rightlist + = "#{@build_list.human_current_duration} / #{@build_list.project.human_average_build_time}" + .both + + - if @build_list.can_publish? and @build_list.save_to_platform.released and @build_list.advisory.nil? + .leftlist= label_tag :create_advisory, t("layout.build_lists.create_advisory") + .rightlist= check_box_tag :create_advisory, 1, false + .both + = f.fields_for @build_list.build_advisory do |f| + = render :partial => 'advisories/form', :locals => {:f => f} + + = submit_tag t("layout.publish"), :confirm => t("layout.confirm"), :name => 'publish' if @build_list.can_publish? and can?(:publish, @build_list) + = submit_tag t("layout.reject_publish"), :confirm => t("layout.confirm"), :name => 'reject_publish' if @build_list.can_reject_publish? and can?(:reject_publish, @build_list) .hr %h3= t("layout.build_lists.items_header") @@ -86,6 +102,25 @@ %td= item.human_status .both +- if @build_list.packages.present? + .hr + %h3= t("layout.build_lists.packages_header") + %table.tablesorter.width565{:cellpadding => "0", :cellspacing => "0"} + %thead + %tr + %th= t("activerecord.attributes.build_list/package.fullname") + %th= t("activerecord.attributes.build_list/package.name") + %th= t("activerecord.attributes.build_list/package.version") + %th= t("activerecord.attributes.build_list/package.release") + %tbody + - @build_list.packages.each do |package| + %tr + %td= package.fullname + %td= package.name + %td= package.version + %td= package.release + .both + :javascript $('article .all').addClass('bigpadding'); diff --git a/config/deploy.rb b/config/deploy.rb index 74734e310..ac5e272f1 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -1,7 +1,6 @@ # -*- encoding : utf-8 -*- -$:.unshift File.expand_path('.') -$:.unshift(File.expand_path('./lib', ENV['rvm_path'])) -set :rvm_type, :user +require 'cape' +require 'capistrano_colors' set :default_environment, { 'LANG' => 'en_US.UTF-8' @@ -34,10 +33,10 @@ set :scm, :git set :repository, "git@github.com:warpc/rosa-build.git" set :deploy_via, :remote_cache -require 'lib/recipes/nginx' -require 'lib/recipes/unicorn' -require 'lib/recipes/bluepill' -require 'lib/recipes/delayed_job' +require './lib/recipes/nginx' +require './lib/recipes/unicorn' +require './lib/recipes/bluepill' +require './lib/recipes/delayed_job' namespace :deploy do task :stub_xml_rpc do @@ -92,7 +91,6 @@ after "deploy:restart", "delayed_job:restart" after "deploy:restart", "deploy:cleanup" -require 'cape' namespace :rake_tasks do Cape do mirror_rake_tasks 'db:seeds' diff --git a/config/environments/production.rb b/config/environments/production.rb index 8c711ab81..37372580c 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -62,7 +62,7 @@ Rosa::Application.configure do config.assets.digest = true # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) - config.assets.precompile += %w(login.css login.js reg_session.css) + config.assets.precompile += %w(login.css login.js reg_session.css tour.css tour.js) end # require 'stub_xml_rpc' diff --git a/config/locales/layout.en.yml b/config/locales/layout.en.yml index 94659ac41..ac1790dd0 100644 --- a/config/locales/layout.en.yml +++ b/config/locales/layout.en.yml @@ -4,6 +4,8 @@ en: turned_on: on turned_off: off + list: List + year: year enter_commit_message: Commit message diff --git a/config/locales/layout.ru.yml b/config/locales/layout.ru.yml index 7b66a589e..ba70c945d 100644 --- a/config/locales/layout.ru.yml +++ b/config/locales/layout.ru.yml @@ -4,6 +4,8 @@ ru: turned_on: включены turned_off: выключены + list: Список + year: год enter_commit_message: Сопровождающее сообщение diff --git a/config/locales/menu.en.yml b/config/locales/menu.en.yml index 750ef9754..c82d72e40 100644 --- a/config/locales/menu.en.yml +++ b/config/locales/menu.en.yml @@ -8,6 +8,7 @@ en: projects: Projects build_lists: Task monitoring groups: Groups + advisories: Advisories bottom_menu: copyright: ROSA Lab © 2012 about: About the company diff --git a/config/locales/menu.ru.yml b/config/locales/menu.ru.yml index 95e068ddd..73c824e21 100644 --- a/config/locales/menu.ru.yml +++ b/config/locales/menu.ru.yml @@ -8,6 +8,7 @@ ru: projects: Проекты build_lists: Мониторинг задач groups: Группы + advisories: Бюллетени bottom_menu: copyright: ROSA Лаб. © 2012 about: О компании diff --git a/config/locales/models/advisory.en.yml b/config/locales/models/advisory.en.yml new file mode 100644 index 000000000..027dd62bf --- /dev/null +++ b/config/locales/models/advisory.en.yml @@ -0,0 +1,22 @@ +en: + layout: + advisories: + list_header: Advisories + form_header: New advisory + project_name: Project + affected_versions: Affected versions + ref_comment: Add links one by row + + flash: + advisories: + + activerecord: + models: + advisory: Advisory + + attributes: + advisory: + created_at: Creation date + advisory_id: Identifier + description: Description + references: References diff --git a/config/locales/models/advisory.ru.yml b/config/locales/models/advisory.ru.yml new file mode 100644 index 000000000..169bf5f70 --- /dev/null +++ b/config/locales/models/advisory.ru.yml @@ -0,0 +1,22 @@ +ru: + layout: + advisories: + list_header: Бюллетени + form_header: Новый бюллетень + project_name: Проект + affected_versions: Применен в версиях + ref_comment: Вставляйте ссылки по одной на строку + + flash: + advisories: + + activerecord: + models: + advisory: Бюллетень + + attributes: + advisory: + created_at: Дата создания + advisory_id: Идентификатор + description: Описание проблемы + references: Ссылки diff --git a/config/locales/models/build_list.en.yml b/config/locales/models/build_list.en.yml index b6654d7ab..9688c14c0 100644 --- a/config/locales/models/build_list.en.yml +++ b/config/locales/models/build_list.en.yml @@ -18,10 +18,8 @@ en: additional_repos: Additional repositories include_repos: Included repositories created_at: Created on - pl: Repository for package storage - pl_id: Repository for package storage - bpl: Platform - bpl_id: Platform + save_to_platform: Repository for package storage + build_for_platform: Platform update_type: Update type build_requires: Build with all the required packages auto_publish: Automated publising @@ -38,6 +36,12 @@ en: version: Version build_list: Build list + build_list/package: + name: Name + fullname: Fullname + release: Release + version: Version + layout: build_lists: filter_header: Filter @@ -50,6 +54,7 @@ en: project_name_search: Search by project name bs_id_not_set: Id has not been configured yet items_header: Build items + packages_header: Container data no_items_data: No data show: Show cancel_success: 'Build canceled' @@ -62,9 +67,13 @@ en: action: Action new_header: New build main_data: Main data + human_current_duration: Build currently takes %{hours} h. %{minutes} min. human_duration: Builded in %{hours} h. %{minutes} min. + attached_advisory: Attached advisory + create_advisory: Create new advisory + ownership: header: Build list ownership owned: My @@ -107,8 +116,8 @@ en: flash: build_list: - saved: Build list for project version '%{project_version}', platform '%{bpl}' and architecture '%{arch}' has been created successfully - save_error: Build list for project version '%{project_version}', platform '%{bpl}' and architecture '%{arch}' could not been created + saved: Build list for project version '%{project_version}', platform '%{build_for_platform}' and architecture '%{arch}' has been created successfully + save_error: Build list for project version '%{project_version}', platform '%{build_for_platform}' and architecture '%{arch}' could not been created no_project_version_selected: Select any version of the project no_project_version_found: Project version '%{project_version}' not found no_arch_or_platform_selected: At least one of architecture of platform must selected diff --git a/config/locales/models/build_list.ru.yml b/config/locales/models/build_list.ru.yml index 8eb14665b..faebb4372 100644 --- a/config/locales/models/build_list.ru.yml +++ b/config/locales/models/build_list.ru.yml @@ -18,10 +18,8 @@ ru: additional_repos: Дополнительные репозитории include_repos: Подключаемые репозитории created_at: Создан - pl: Репозиторий для сохранения пакетов - pl_id: Репозиторий для сохранения пакетов - bpl: Платформа - bpl_id: Платформа + save_to_platform: Репозиторий для сохранения пакетов + build_for_platform: Платформа update_type: Критичность обновления build_requires: Пересборка с зависимостями auto_publish: Автоматическая публикация @@ -37,6 +35,12 @@ ru: version: Версия build_list: Сборочный лист + build_list/package: + name: Название + fullname: Полное имя + release: Релиз + version: Версия + layout: build_lists: filter_header: Фильтр @@ -49,6 +53,7 @@ ru: project_name_search: Поиск по названию проекта bs_id_not_set: Id еще не присвоен items_header: Элементы сборки + packages_header: Данные о контейнере no_items_data: Данных нет show: Просмотр cancel_success: 'Сборка отменена.' @@ -65,6 +70,9 @@ ru: human_current_duration: Сборка длится уже %{hours} ч. %{minutes} мин. human_duration: Собрано за %{hours} ч. %{minutes} мин. + attached_advisory: Связанный бюллетень + create_advisory: Создать новый бюллетень + ownership: header: Принадлежность заданий owned: Мне @@ -107,8 +115,8 @@ ru: flash: build_list: - saved: Билд лист для версии '%{project_version}', платформы '%{bpl}' и архитектуры '%{arch}' создан успешно - save_error: Не удалось сохранить билд лист для версии '%{project_version}', платформы '%{bpl}' и архитектуры '%{arch}' + saved: Билд лист для версии '%{project_version}', платформы '%{build_for_platform}' и архитектуры '%{arch}' создан успешно + save_error: Не удалось сохранить билд лист для версии '%{project_version}', платформы '%{build_for_platform}' и архитектуры '%{arch}' no_project_version_selected: Выберите какую-нибудь версию no_project_version_found: Выбранная версия '%{project_version}' не найдена no_arch_or_platform_selected: Выберите хотя бы одну архитектуру и платформу diff --git a/config/locales/models/project.en.yml b/config/locales/models/project.en.yml index 8b5e67b95..788a10241 100644 --- a/config/locales/models/project.en.yml +++ b/config/locales/models/project.en.yml @@ -88,3 +88,6 @@ en: group: Group default_branch: Default branch is_rpm: Project is a packet + 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 c97f6c03c..c0a806d18 100644 --- a/config/locales/models/project.ru.yml +++ b/config/locales/models/project.ru.yml @@ -88,3 +88,6 @@ ru: group: Группа default_branch: Ветка по умолчанию is_rpm: Проект является пакетом + errors: + project: + uname: В имени можно использовать только строчные символы латинского алфавита (a-z), цифры (0-9) и символ нижнего подчеркивания (_) diff --git a/config/locales/title.en.yml b/config/locales/title.en.yml index 198c74254..ffaa005c3 100644 --- a/config/locales/title.en.yml +++ b/config/locales/title.en.yml @@ -3,26 +3,29 @@ en: 'Editing' at: at users: - profile: - title: 'Your Profile' - build_lists: - index: - title: 'Projects Monitoring' - product_build_lists: - index: - title: 'Products Monitoring' - git: - commits: + settings: + profile: + title: 'Your Profile' + projects: + build_lists: index: - title: 'Commit History' - issues: - index: - title: 'Tracker' - wiki: - compare: - title: 'Compare Revisions' - searching: - title: 'Search in Wiki' + title: 'Projects Monitoring' + git: + commits: + index: + title: 'Commit History' + issues: + index: + title: 'Tracker' + wiki: + compare: + title: 'Compare Revisions' + searching: + title: 'Search in Wiki' + platforms: + product_build_lists: + index: + title: 'Products Monitoring' pull_requests: index: title: 'Pull Requests' diff --git a/config/locales/title.ru.yml b/config/locales/title.ru.yml index 6f5793063..202d3f2dc 100644 --- a/config/locales/title.ru.yml +++ b/config/locales/title.ru.yml @@ -3,26 +3,29 @@ ru: 'Редактирование' at: at users: - profile: - title: 'Ваш профиль' - build_lists: - index: - title: 'Мониторинг проектов' - product_build_lists: - index: - title: 'Мониторинг продуктов' - git: - commits: + settings: + profile: + title: 'Ваш профиль' + projects: + build_lists: index: - title: 'История коммитов' - issues: - index: - title: 'Трекер' - wiki: - compare: - title: 'Сравнение версий' - searching: - title: 'Поиск в вики' + title: 'Мониторинг проектов' + git: + commits: + index: + title: 'История коммитов' + issues: + index: + title: 'Трекер' + wiki: + compare: + title: 'Сравнение версий' + searching: + title: 'Поиск в вики' + platforms: + product_build_lists: + index: + title: 'Мониторинг продуктов' pull_requests: index: title: 'Запросы на слияние' diff --git a/config/locales/tour.en.yml b/config/locales/tour.en.yml new file mode 100644 index 000000000..2f1f2fd5f --- /dev/null +++ b/config/locales/tour.en.yml @@ -0,0 +1,51 @@ +en: + tour: + read_more: more... + projects: Project Management + sources: Source Code + builds: Package Building + + repo: Personal repository + monitoring: Task monitoring + source: Source code online + history: File history + annotation: File blame + edit: Online editor + control: Project Management + git: Git Wiki + tracker: Lightweight task tracker + + projects_header: Every git repository in ABF is accompanied by tools necessary to manage a project, be it a public project or a private one. + sources_header: ABF is full-functional git-hosting with convenient Web interface. + builds_header: | + ABF is not just a hosting for source code, but a system to build and publish packages. + Build your projects for large variety of distributions and hardware platforms in your personal repository! + + repo_description: | + Personal repository provides you with an easy way to distribute your software among great number of Linux users by means of standard ways of software delivery. + ABF will take care of package dependencies from both main repositories or extra and personal ones. Published a new package version? + Users will be automatically notified about available update. + builds_description: | + ABF provides you with power to build projects for large variety of distributions and hardware platforms. No additional efforts from your side! + monitoring_description: | + It is easy to get lost in large amount of tasks, but smart monitoring will focus your attention on those tasks that really matter for you. + source_description: | + We have focused on making access to the source code easy and transparent. Every file pushed to git repository will instantly become available for online access, + so you can share it with other developers even if they don't use Git. Home page of every project contains list of project files, + as well as information about recent changes. You can immediately see the most important part of your project: the code. + history_description: | + Every file in git repository has history of modifications which can be easily looked through using ABF to see who and when modified the file + and which changes were introduced by particular commits. + annotation_description: 'Looking for the author of a particular code fragment? Just open the file blame to see who modified that fragment for the last time and in which commit.' + edit_description: Need to quickly edit some file? Want to fix syntax error from your mobile phone? No problem. We provide you with a simple editor for every file in git repository. + control_description: | + There are 3 possible levels of privileges for project members: read-only, read/write, and administration level. A project member can designate a real user + or a group of developers. Both projects and groups may have unlimited number of members (every of which can be in turn a user or a group). + git_description: | + Project wiki is based on Gollum — open wiki engine developed by GitHub. In fact, this is a full-function git repository which can be cloned, used offline, + modified and pushed back to server, as if it were a usual source code. Convenient web editor allows to modify wiki online. + Now information about your project will be never lost and will be always available for modifications in any editor! +

Note: for private projects, wiki is accessible by project team only. Wiki of a public project can be read by everyone. + tracker_description: | + Every project may use a lightweight and simple task tracker. Labels and assignments will allow not to get lost in tasks, + while convenient interface will allow to concentrate on a real work, not filling huge forms. diff --git a/config/locales/tour.ru.yml b/config/locales/tour.ru.yml new file mode 100644 index 000000000..22408eac3 --- /dev/null +++ b/config/locales/tour.ru.yml @@ -0,0 +1,61 @@ +ru: + tour: + read_more: Читать далее... + projects: Управление проектами + sources: Исходный код + builds: Сборка пакетов + + repo: Персональный репозиторий + monitoring: Мониторинг + source: Исходный код онлайн + history: История файла + annotation: Аннотация файла + edit: Редактирования онлайн + control: Управление проектами + git: Git Wiki + tracker: Легкий трекер задач + + projects_header: | + Каждый git-репозиторий на ABF поставляется с инструментами, необходимыми для управления проектами, + вне зависимости от того, публичный или приватный проект. + sources_header: ABF — полноценный git-хостинг с удобным веб-интерфейсом. + builds_header: | + ABF — это не только хостинг исходного кода, но и система сборки и хостинга пакетов. + Собирайте свои проекты под множество дистрибутивов и архитектур в свой персональный репозиторий. + + repo_description: | + Персональный репозиторий — быстрый и легкий способ распространить свое ПО множеству Linux пользователей + различных дистрибутивов, используя стандартный механизм доставки ПО. + ABF позаботится о зависимостях ПО из основных репозиториев и/или дополнительных персональных репозиториев. + Опубликовали новую версию? Пользователи автоматически получат оповещение о доступности обновления. + builds_description: | + ABF позволяет собрать ваши проекты под множество архитектур и дистрибутивов, используя свои вычислительные мощности. + Никаких затрат с вашей стороны! + monitoring_description: | + В большом числе сборочных заданий легко потеряться, поэтому мониторинг сборки фокусирует ваше внимание только на том, + что действительно важно. + source_description: | + Мы сфокусировались на том, чтобы сделать исходный код доступным и прозрачным. Все, что вы выложите в git-репозиторий, + мгновенно станет доступным для просмотра в режиме онлайн, чтобы вы могли поделиться им с людьми, даже если они не + используют Git. На главной странице каждого проекта есть список файлов проекта, а также информация о последнем изменении. + Вы можете сразу увидеть самое важное в вашем проекте: код. + history_description: 'Каждый файл в git-репозитории имеет историю, которую вы легко можете посмотреть: кто, когда и что в нем поменял.' + annotation_description: | + Ищете автора фрагмента кода? Откройте аннотацию файла (Blame), чтобы увидеть: + кто и в каком коммите последний изменял данный фрагмент. + edit_description: | + Вам нужно быстро внести изменение в файл? Исправить орфографические ошибки c вашего мобильного телефона? + Мы предлагаем простой редактор для каждого файла в git-репозитории. + control: | + Существует 3 возможных роли для участника проекта: только чтение, чтение/запись и административный уровень. + Участником проекта может выступать как пользователь, так и группа. Проект, как и группа, может иметь неограниченное + число участников (пользователей, групп или всех вместе). + git: | + Вики проекта создана с помощью Gollum — открытого вики-движка, созданного GitHub. В основе своей это полноценный + git-репозиторий, который можно клонировать, использовать в режиме офлайн, изменять и загружать изменения обратно на + сервер, как в случае с обычным кодом. Удобный веб-редактор позволит работать с ней в онлайн. Теперь данные о проекте не + пропадут и доступны для редактирования в любимом редакторе! +

Примечание: для приватного проекта вики доступна только его участникам. Для публичного — всем для чтения. + tracker: | + Каждый проект также может использовать легкий и простой трекер задач. Метки и назначения позволят не потеряться среди + задач, а понятный интерфейс позволит сконцентрироваться на работе, а не на заполнении огромных формуляров. diff --git a/config/routes.rb b/config/routes.rb index 98f8303fe..d5d279bb2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,6 +9,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/ get '/activity_feeds.:format' => 'activity_feeds#index', :as => 'atom_activity_feeds', :format => /atom/ if APP_CONFIG['anonymous_access'] @@ -20,6 +21,22 @@ Rosa::Application.routes.draw do root :to => 'activity_feeds#index' end + namespace :admin do + resources :users do + get :list, :on => :collection + end + resources :register_requests, :only => [:index] do + put :update, :on => :collection + member do + get :approve + get :reject + end + end + resources :event_logs, :only => :index + end + + resources :advisories, :only => [:index, :show] + scope :module => 'platforms' do resources :platforms do resources :private_users, :except => [:show, :destroy, :update] @@ -49,20 +66,6 @@ Rosa::Application.routes.draw do resources :product_build_lists, :only => [:index] end - namespace :admin do - resources :users do - get :list, :on => :collection - end - resources :register_requests, :only => [:index] do - put :update, :on => :collection - member do - get :approve - get :reject - end - end - resources :event_logs, :only => :index - end - scope :module => 'users' do resources :settings, :only => [] do collection do @@ -82,6 +85,8 @@ Rosa::Application.routes.draw do end scope :module => 'groups' do + get '/groups/new' => 'profile#new' # need to force next route exclude :id => 'new' + get '/groups/:id' => redirect("/%{id}"), :as => :profile_group # override default group show route resources :groups, :controller => 'profile' do get :autocomplete_group_uname, :on => :collection delete :remove_user, :on => :member @@ -105,79 +110,70 @@ Rosa::Application.routes.draw do match 'build_lists/new_bbdt', :to => "build_lists#new_bbdt" match 'product_status', :to => 'product_build_lists#status_build' - resources :build_lists, :only => [:index, :show] do + resources :build_lists, :only => [:index, :show, :update] do member do put :cancel - put :publish - put :reject_publish end collection { post :search } end resources :projects, :only => [:index, :new, :create] - end - scope ':owner_name' do # Owner - constraints OwnerConstraint.new(User) do - get '/' => 'users/profile#show', :as => :user - end - constraints OwnerConstraint.new(Group, true) do - get '/' => 'groups/profile#show', :as => :group_profile - end - scope ':project_name', :as => 'project', :module => 'projects' do - resources :wiki do - collection do - match '_history' => 'wiki#wiki_history', :as => :history, :via => :get - match '_access' => 'wiki#git', :as => :git, :via => :get - match '_revert/:sha1/:sha2' => 'wiki#revert_wiki', :as => :revert, :via => [:get, :post] - match '_compare' => 'wiki#compare_wiki', :as => :compare, :via => :post - #match '_compare/:versions' => 'wiki#compare_wiki', :versions => /.*/, :as => :compare_versions, :via => :get - match '_compare/:versions' => 'wiki#compare_wiki', :versions => /([a-f0-9\^]{6,40})(\.\.\.[a-f0-9\^]{6,40})/, :as => :compare_versions, :via => :get - post :preview - get :search - get :pages - end - member do - get :history - get :edit - match 'revert/:sha1/:sha2' => 'wiki#revert', :as => :revert_page, :via => [:get, :post] - match ':ref' => 'wiki#show', :as => :versioned, :via => :get - post :compare - #match 'compare/*versions' => 'wiki#compare', :as => :compare_versions, :via => :get - match 'compare/:versions' => 'wiki#compare', :versions => /([a-f0-9\^]{6,40})(\.\.\.[a-f0-9\^]{6,40})/, :as => :compare_versions, :via => :get + scope ':owner_name/:project_name', :constraints => {:project_name => Project::NAME_REGEXP} do # project + scope :as => 'project' do + resources :wiki do + collection do + match '_history' => 'wiki#wiki_history', :as => :history, :via => :get + match '_access' => 'wiki#git', :as => :git, :via => :get + match '_revert/:sha1/:sha2' => 'wiki#revert_wiki', :as => :revert, :via => [:get, :post] + match '_compare' => 'wiki#compare_wiki', :as => :compare, :via => :post + #match '_compare/:versions' => 'wiki#compare_wiki', :versions => /.*/, :as => :compare_versions, :via => :get + match '_compare/:versions' => 'wiki#compare_wiki', :versions => /([a-f0-9\^]{6,40})(\.\.\.[a-f0-9\^]{6,40})/, :as => :compare_versions, :via => :get + post :preview + get :search + get :pages + end + member do + get :history + get :edit + match 'revert/:sha1/:sha2' => 'wiki#revert', :as => :revert_page, :via => [:get, :post] + match ':ref' => 'wiki#show', :as => :versioned, :via => :get + + post :compare + #match 'compare/*versions' => 'wiki#compare', :as => :compare_versions, :via => :get + match 'compare/:versions' => 'wiki#compare', :versions => /([a-f0-9\^]{6,40})(\.\.\.[a-f0-9\^]{6,40})/, :as => :compare_versions, :via => :get + end end - end - resources :issues, :except => :edit do - resources :comments, :only => [:edit, :create, :update, :destroy] - resources :subscribes, :only => [:create, :destroy] - collection do - post :create_label - get :search_collaborators + resources :issues, :except => :edit do + resources :comments, :only => [:edit, :create, :update, :destroy] + resources :subscribes, :only => [:create, :destroy] + collection do + post :create_label + get :search_collaborators + end end - end - post "/labels/:label_id" => "issues#destroy_label", :as => :issues_delete_label - post "/labels/:label_id/update" => "issues#update_label", :as => :issues_update_label - resources :build_lists, :only => [:index, :new, :create] do - collection { post :search } - end - resources :collaborators do - get :find, :on => :collection - end - resources :pull_requests, :except => [:destroy, :new] do - collection do - post '/new' => 'pull_requests#new' - get :autocomplete_base_project_name - get :autocomplete_head_project_name - get :autocomplete_base_ref - get :autocomplete_head_ref + post "/labels/:label_id" => "issues#destroy_label", :as => :issues_delete_label + post "/labels/:label_id/update" => "issues#update_label", :as => :issues_update_label + resources :build_lists, :only => [:index, :new, :create] do + collection { post :search } end - member do - put :merge, :as => 'merge' + resources :collaborators do + get :find, :on => :collection + end + resources :pull_requests, :except => [:destroy, :new] do + collection do + post '/new' => 'pull_requests#new' + get :autocomplete_base_project_name + get :autocomplete_head_project_name + get :autocomplete_base_ref + get :autocomplete_head_ref + end + member do + put :merge, :as => 'merge' + end end end - end - scope ':project_name', :module => 'projects' do # Resource get '/edit' => 'projects#edit', :as => :edit_project put '/' => 'projects#update' @@ -214,4 +210,13 @@ Rosa::Application.routes.draw do get '/archive/:format/tree/:treeish' => "git/trees#archive", :defaults => {:treeish => :master}, :as => :archive, :format => /zip|tar/ end end + + scope ':uname' do # project owner profile + constraints OwnerConstraint.new(User) do + get '/' => 'users/profile#show', :as => :user + end + constraints OwnerConstraint.new(Group, true) do + get '/' => 'groups/profile#show', :as => :group + end + end end diff --git a/config/schedule.rb b/config/schedule.rb index 69ec02b5d..85a3bd556 100644 --- a/config/schedule.rb +++ b/config/schedule.rb @@ -10,3 +10,7 @@ every 1.day, :at => '4:00 am' do rake "import:sync:all", :output => 'log/sync.log' end + +every 1.day, :at => '3:50 am' do + rake "buildlist:clear:outdated", :output => 'log/build_list_clear.log' +end diff --git a/db/migrate/20120428053303_create_advisories.rb b/db/migrate/20120428053303_create_advisories.rb new file mode 100644 index 000000000..e1a6ee8fc --- /dev/null +++ b/db/migrate/20120428053303_create_advisories.rb @@ -0,0 +1,16 @@ +class CreateAdvisories < ActiveRecord::Migration + def change + create_table :advisories do |t| + t.string :advisory_id + t.integer :project_id + t.text :description, :default => '' + t.text :references, :default => '' + t.text :update_type, :default => '' + + t.timestamps + end + add_index :advisories, :advisory_id, :unique => true + add_index :advisories, :project_id + add_index :advisories, :update_type + end +end diff --git a/db/migrate/20120428054604_create_advisories_platforms.rb b/db/migrate/20120428054604_create_advisories_platforms.rb new file mode 100644 index 000000000..aded3af7b --- /dev/null +++ b/db/migrate/20120428054604_create_advisories_platforms.rb @@ -0,0 +1,18 @@ +class CreateAdvisoriesPlatforms < ActiveRecord::Migration + def up + create_table :advisories_platforms, :id => false do |t| + t.integer :advisory_id + t.integer :platform_id + end + add_index :advisories_platforms, :advisory_id + add_index :advisories_platforms, :platform_id + add_index :advisories_platforms, [:advisory_id, :platform_id], :name => :advisory_platform_index, :unique => true + end + + def down + remove_index :advisories_platforms, :column => :advisory_id + remove_index :advisories_platforms, :column => :platform_id + remove_index :advisories_platforms, :name => :advisory_platform_index + drop_table :advisories_platforms + end +end diff --git a/db/migrate/20120428070521_add_advisory_id_to_build_lists.rb b/db/migrate/20120428070521_add_advisory_id_to_build_lists.rb new file mode 100644 index 000000000..c73f47e76 --- /dev/null +++ b/db/migrate/20120428070521_add_advisory_id_to_build_lists.rb @@ -0,0 +1,7 @@ +class AddAdvisoryIdToBuildLists < ActiveRecord::Migration + def change + add_column :build_lists, :advisory_id, :integer + add_index :build_lists, :advisory_id + + end +end diff --git a/db/migrate/20120428105843_rename_pl_bpl_in_build_list.rb b/db/migrate/20120428105843_rename_pl_bpl_in_build_list.rb new file mode 100644 index 000000000..d9f79b877 --- /dev/null +++ b/db/migrate/20120428105843_rename_pl_bpl_in_build_list.rb @@ -0,0 +1,15 @@ +class RenamePlBplInBuildList < ActiveRecord::Migration + def up + change_table :build_lists do |t| + t.rename :pl_id, :save_to_platform_id + t.rename :bpl_id, :build_for_platform_id + end + end + + def down + change_table :build_lists do |t| + t.rename :save_to_platform_id, :pl_id + t.rename :build_for_platform_id, :bpl_id + end + end +end diff --git a/db/migrate/20120505101650_add_build_priority_to_users.rb b/db/migrate/20120505101650_add_build_priority_to_users.rb new file mode 100644 index 000000000..45e2efae3 --- /dev/null +++ b/db/migrate/20120505101650_add_build_priority_to_users.rb @@ -0,0 +1,11 @@ +class AddBuildPriorityToUsers < ActiveRecord::Migration + def up + add_column :users, :build_priority, :integer, :default => 50 + User.update_all :build_priority => 50 + end + + def down + remove_column :users, :build_priority + end + +end diff --git a/db/migrate/20120512102707_create_build_list_packages.rb b/db/migrate/20120512102707_create_build_list_packages.rb new file mode 100644 index 000000000..1e6b1acd9 --- /dev/null +++ b/db/migrate/20120512102707_create_build_list_packages.rb @@ -0,0 +1,19 @@ +class CreateBuildListPackages < ActiveRecord::Migration + def change + create_table :build_list_packages do |t| + t.references :build_list + t.references :project + t.references :platform + t.string :fullname + t.string :name + t.string :version + t.string :release + t.string :package_type + + t.timestamps + end + add_index :build_list_packages, :build_list_id + add_index :build_list_packages, :project_id + add_index :build_list_packages, :platform_id + end +end diff --git a/db/schema.rb b/db/schema.rb index daf42a5b7..d9212a9bd 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 => 20120425190938) do +ActiveRecord::Schema.define(:version => 20120512102707) do create_table "activity_feeds", :force => true do |t| t.integer "user_id", :null => false @@ -21,6 +21,29 @@ ActiveRecord::Schema.define(:version => 20120425190938) do t.datetime "updated_at", :null => false end + create_table "advisories", :force => true do |t| + t.string "advisory_id" + t.integer "project_id" + t.text "description", :default => "" + t.text "references", :default => "" + t.text "update_type", :default => "" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "advisories", ["advisory_id"], :name => "index_advisories_on_advisory_id", :unique => true + add_index "advisories", ["project_id"], :name => "index_advisories_on_project_id" + add_index "advisories", ["update_type"], :name => "index_advisories_on_update_type" + + create_table "advisories_platforms", :id => false, :force => true do |t| + t.integer "advisory_id" + t.integer "platform_id" + end + + add_index "advisories_platforms", ["advisory_id"], :name => "index_advisories_platforms_on_advisory_id" + add_index "advisories_platforms", ["advisory_id", "platform_id"], :name => "advisory_platform_index", :unique => true + add_index "advisories_platforms", ["platform_id"], :name => "index_advisories_platforms_on_platform_id" + create_table "arches", :force => true do |t| t.string "name", :null => false t.datetime "created_at", :null => false @@ -52,6 +75,23 @@ ActiveRecord::Schema.define(:version => 20120425190938) do add_index "build_list_items", ["build_list_id"], :name => "index_build_list_items_on_build_list_id" + create_table "build_list_packages", :force => true do |t| + t.integer "build_list_id" + t.integer "project_id" + t.integer "platform_id" + t.string "fullname" + t.string "name" + t.string "version" + t.string "release" + t.string "package_type" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "build_list_packages", ["build_list_id"], :name => "index_build_list_packages_on_build_list_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" + create_table "build_lists", :force => true do |t| t.integer "bs_id" t.string "container_path" @@ -60,25 +100,27 @@ ActiveRecord::Schema.define(:version => 20120425190938) do t.integer "project_id" t.integer "arch_id" t.datetime "notified_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.boolean "is_circle", :default => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.boolean "is_circle", :default => false t.text "additional_repos" t.string "name" - t.boolean "build_requires", :default => false + t.boolean "build_requires", :default => false t.string "update_type" - t.integer "bpl_id" - t.integer "pl_id" + t.integer "build_for_platform_id" + t.integer "save_to_platform_id" t.text "include_repos" t.integer "user_id" - t.boolean "auto_publish", :default => true + t.boolean "auto_publish", :default => true t.string "package_version" t.string "commit_hash" - t.integer "priority", :default => 0, :null => false + t.integer "priority", :default => 0, :null => false t.datetime "started_at" t.integer "duration" + t.integer "advisory_id" end + 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", ["bs_id"], :name => "index_build_lists_on_bs_id", :unique => true add_index "build_lists", ["project_id"], :name => "index_build_lists_on_project_id" @@ -331,8 +373,8 @@ ActiveRecord::Schema.define(:version => 20120425190938) do create_table "users", :force => true do |t| t.string "name" - t.string "email", :default => "", :null => false - t.string "encrypted_password", :limit => 128, :default => "", :null => false + t.string "email", :default => "", :null => false + t.string "encrypted_password", :default => "", :null => false t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" @@ -341,9 +383,11 @@ ActiveRecord::Schema.define(:version => 20120425190938) do t.text "ssh_key" t.string "uname" t.string "role" - t.string "language", :default => "en" - t.datetime "reset_password_sent_at" - t.integer "own_projects_count", :default => 0, :null => false + t.string "language", :default => "en" + t.integer "own_projects_count", :default => 0, :null => false + t.string "confirmation_token" + t.datetime "confirmed_at" + t.datetime "confirmation_sent_at" t.text "professional_experience" t.string "site" t.string "company" @@ -356,6 +400,7 @@ ActiveRecord::Schema.define(:version => 20120425190938) do t.string "unlock_token" t.datetime "locked_at" t.string "authentication_token" + t.integer "build_priority", :default => 50 end add_index "users", ["authentication_token"], :name => "index_users_on_authentication_token" diff --git a/lib/ext/rails/owner_constraint.rb b/lib/ext/rails/owner_constraint.rb index 93b32935a..10f091e3f 100644 --- a/lib/ext/rails/owner_constraint.rb +++ b/lib/ext/rails/owner_constraint.rb @@ -7,6 +7,6 @@ class OwnerConstraint end def matches?(request) - @class_name.send(@finder, request.params[:owner_name]).present? + @class_name.send(@finder, request.params[:uname]).present? end end diff --git a/lib/ext/rails/reserved_name_validator.rb b/lib/ext/rails/reserved_name_validator.rb index d53b045d8..7d578e6c4 100644 --- a/lib/ext/rails/reserved_name_validator.rb +++ b/lib/ext/rails/reserved_name_validator.rb @@ -23,6 +23,7 @@ class ReservedNameValidator < ActiveModel::EachValidator unfollow unsubscribe url user widget widgets wiki xfn xmpp + tour } def reserved_names diff --git a/lib/tasks/buildlist.rake b/lib/tasks/buildlist.rake new file mode 100644 index 000000000..ea6a40eff --- /dev/null +++ b/lib/tasks/buildlist.rake @@ -0,0 +1,16 @@ + +namespace :buildlist do + + namespace :clear do + desc 'Remove outdated unpublished BuildLists' + task :outdated => :environment do + say "Removing outdated BuildLists" + outdated = BuildList.outdated + say "There are #{outdated.count} outdated BuildLists at #{Time.now}" + + BuildList.outdated.destroy_all + + say "Outdated BuildLists was successfully removed" + end + end +end diff --git a/lib/tasks/migrate_from_mount_to_symlink.rake b/lib/tasks/migrate_from_mount_to_symlink.rake new file mode 100644 index 000000000..f85344a3e --- /dev/null +++ b/lib/tasks/migrate_from_mount_to_symlink.rake @@ -0,0 +1,13 @@ +namespace :downloads do + + desc "Migrate from mount to symlinks" + task :migrate => :environment do + Platform.opened.each do |pl| + system("sudo umount #{pl.symlink_path}") + system("sudo rm -Rf #{pl.symlink_path}") + + pl.symlink_directory + end + end + +end diff --git a/spec/controllers/groups/members_controller_spec.rb b/spec/controllers/groups/members_controller_spec.rb index a245165e8..5e3046f8b 100644 --- a/spec/controllers/groups/members_controller_spec.rb +++ b/spec/controllers/groups/members_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Groups::MembersController do before(:each) do - stub_rsync_methods + stub_symlink_methods @group = FactoryGirl.create(:group) @user = @group.owner set_session_for @user diff --git a/spec/controllers/groups/profile_controller_spec.rb b/spec/controllers/groups/profile_controller_spec.rb index 73605fa66..21c62b7df 100644 --- a/spec/controllers/groups/profile_controller_spec.rb +++ b/spec/controllers/groups/profile_controller_spec.rb @@ -69,7 +69,7 @@ end describe Groups::ProfileController do before(:each) do - stub_rsync_methods + stub_symlink_methods @group = FactoryGirl.create(:group) @another_user = FactoryGirl.create(:user) @create_params = {:group => {:description => 'grp1', :uname => 'un_grp1'}} diff --git a/spec/controllers/platforms/platforms_controller_spec.rb b/spec/controllers/platforms/platforms_controller_spec.rb index 5ec928b1c..242315f10 100644 --- a/spec/controllers/platforms/platforms_controller_spec.rb +++ b/spec/controllers/platforms/platforms_controller_spec.rb @@ -35,7 +35,7 @@ end describe Platforms::PlatformsController do before(:each) do - stub_rsync_methods + stub_symlink_methods @platform = FactoryGirl.create(:platform) @personal_platform = FactoryGirl.create(:platform, :platform_type => 'personal') diff --git a/spec/controllers/platforms/product_build_lists_controller_spec.rb b/spec/controllers/platforms/product_build_lists_controller_spec.rb index c79828492..a08fc67d6 100644 --- a/spec/controllers/platforms/product_build_lists_controller_spec.rb +++ b/spec/controllers/platforms/product_build_lists_controller_spec.rb @@ -26,7 +26,7 @@ end describe Platforms::ProductBuildListsController do before(:each) do - stub_rsync_methods + stub_symlink_methods end context 'crud' do diff --git a/spec/controllers/platforms/products_controller_spec.rb b/spec/controllers/platforms/products_controller_spec.rb index 7490675e9..e90d48cbc 100644 --- a/spec/controllers/platforms/products_controller_spec.rb +++ b/spec/controllers/platforms/products_controller_spec.rb @@ -24,7 +24,7 @@ end describe Platforms::ProductsController do before(:each) do - stub_rsync_methods + stub_symlink_methods @another_user = FactoryGirl.create(:user) @platform = FactoryGirl.create(:platform) diff --git a/spec/controllers/platforms/repositories_controller_spec.rb b/spec/controllers/platforms/repositories_controller_spec.rb index 5fec835cc..35120683d 100644 --- a/spec/controllers/platforms/repositories_controller_spec.rb +++ b/spec/controllers/platforms/repositories_controller_spec.rb @@ -67,7 +67,7 @@ end describe Platforms::RepositoriesController do before(:each) do - stub_rsync_methods + stub_symlink_methods @platform = FactoryGirl.create(:platform) @repository = FactoryGirl.create(:repository, :platform => @platform) diff --git a/spec/controllers/projects/build_lists_controller_spec.rb b/spec/controllers/projects/build_lists_controller_spec.rb index 3eb62db7c..d941b5f02 100644 --- a/spec/controllers/projects/build_lists_controller_spec.rb +++ b/spec/controllers/projects/build_lists_controller_spec.rb @@ -64,7 +64,7 @@ describe Projects::BuildListsController do end end - before { stub_rsync_methods } + before { stub_symlink_methods } context 'crud' do before(:each) do @@ -72,12 +72,12 @@ describe Projects::BuildListsController do @create_params = { :build_list => { :project_version => 'latest_master', - :pl_id => platform.id, + :save_to_platform_id => platform.id, :update_type => 'security', :include_repos => [platform.repositories.first.id] }, :arches => [FactoryGirl.create(:arch).id], - :bpls => [platform.id] + :build_for_platforms => [platform.id] } any_instance_of(Project, :versions => ['v1.0', 'v2.0']) end @@ -284,7 +284,7 @@ describe Projects::BuildListsController do @build_list2 = FactoryGirl.create(:build_list_core) @build_list3 = FactoryGirl.create(:build_list_core) @build_list4 = FactoryGirl.create(:build_list_core, :created_at => (Time.now - 1.day), - :project => @build_list3.project, :pl => @build_list3.pl, + :project => @build_list3.project, :save_to_platform => @build_list3.save_to_platform, :arch => @build_list3.arch) end @@ -344,10 +344,28 @@ describe Projects::BuildListsController do end describe 'status_build' do - before { @item = build_list.items.create(:name => build_list.project.name, :version => build_list.project_version, :level => 0) } + before do + @item = build_list.items.create(:name => build_list.project.name, :version => build_list.project_version, :level => 0) + repo = build_list.save_to_platform.repositories.first + repo.projects << build_list.project + @project2 = FactoryGirl.create(:project) + repo.projects << @project2 + end def do_get - get :status_build, :id => build_list.bs_id, :package_name => build_list.project.name, :status => BuildServer::SUCCESS, :container_path => '/path/to' + get :status_build, :id => build_list.bs_id, :package_name => build_list.project.name, :status => BuildServer::SUCCESS, :container_path => '/path/to', + :pkg_info => ActiveSupport::JSON.encode({'srpm' => {'fullname' => 'srpm_filename.srpm', + 'name' => build_list.project.name, + 'version' => 'version1', + 'release' => 'release1'}, + 'rpm' => [{'fullname' => 'filename1.rpm', + 'name' => build_list.project.name, + 'version' => 'version2', + 'release' => 'release2'}, + {'fullname' => 'filename2.rpm', + 'name' => @project2.name, + 'version' => 'version2', + 'release' => 'release2'}]}) build_list.reload @item.reload end @@ -356,6 +374,19 @@ describe Projects::BuildListsController do it { lambda{ do_get }.should change(@item, :status) } it { lambda{ do_get }.should change(build_list, :container_path) } it { lambda{ do_get }.should change(build_list, :updated_at) } + it('should create packages for build list') { lambda{ do_get }.should change(build_list.packages, :count).to(3) } + it 'should create correct packages for build list' do + do_get + package = build_list.packages.order('created_at ASC').first + package.fullname.should == 'srpm_filename.srpm' + package.name.should == build_list.project.name + package.version.should == 'version1' + package.release.should == 'release1' + package.package_type == 'source' + package.build_list.should == build_list + package.platform.should == build_list.save_to_platform + package.project.should == build_list.project + end end describe 'pre_build' do diff --git a/spec/controllers/projects/collaborators_controller_spec.rb b/spec/controllers/projects/collaborators_controller_spec.rb index f40f0b3c8..5c8d320c2 100644 --- a/spec/controllers/projects/collaborators_controller_spec.rb +++ b/spec/controllers/projects/collaborators_controller_spec.rb @@ -64,7 +64,7 @@ end describe Projects::CollaboratorsController do before(:each) do - stub_rsync_methods + stub_symlink_methods @project = FactoryGirl.create(:project) @another_user = FactoryGirl.create(:user) @member_user = FactoryGirl.create(:user) diff --git a/spec/controllers/projects/comments_controller_for_commit_spec.rb b/spec/controllers/projects/comments_controller_for_commit_spec.rb index 9cc131c3e..3ddce850e 100644 --- a/spec/controllers/projects/comments_controller_for_commit_spec.rb +++ b/spec/controllers/projects/comments_controller_for_commit_spec.rb @@ -76,7 +76,7 @@ end describe Projects::CommentsController do before(:each) do - stub_rsync_methods + stub_symlink_methods @project = FactoryGirl.create(:project) %x(cp -Rf #{Rails.root}/spec/tests.git/* #{@project.git_repository.path}) # maybe FIXME ? @commit = @project.git_repository.commits.first diff --git a/spec/controllers/projects/comments_controller_spec.rb b/spec/controllers/projects/comments_controller_spec.rb index 41d6009b4..c04b09c58 100644 --- a/spec/controllers/projects/comments_controller_spec.rb +++ b/spec/controllers/projects/comments_controller_spec.rb @@ -72,7 +72,7 @@ end describe Projects::CommentsController do before(:each) do - stub_rsync_methods + stub_symlink_methods @project = FactoryGirl.create(:project) @issue = FactoryGirl.create(:issue, :project_id => @project.id, :user => FactoryGirl.create(:user)) diff --git a/spec/controllers/projects/git/git_trees_controller_spec.rb b/spec/controllers/projects/git/git_trees_controller_spec.rb index f48f8afc3..ce9884232 100644 --- a/spec/controllers/projects/git/git_trees_controller_spec.rb +++ b/spec/controllers/projects/git/git_trees_controller_spec.rb @@ -8,24 +8,24 @@ describe Projects::Git::TreesController do end before(:each) do - stub_rsync_methods + stub_symlink_methods @project = FactoryGirl.create(:project) @another_user = FactoryGirl.create(:user) - @params = {:project_id => @project.id, :format => 'tar'} + @params = {:owner_name => @project.owner.uname, :project_name => @project.name} 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 + 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 + get :archive, @params.merge(:format => 'tar') response.code.should == '401' end end @@ -35,7 +35,7 @@ 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 }.to raise_error(ActiveRecord::RecordNotFound) + expect { get :archive, @params.merge(:format => 'tar') }.to raise_error(ActiveRecord::RecordNotFound) end it 'should not be able to injection code with format' do @@ -56,7 +56,7 @@ describe Projects::Git::TreesController do @user = FactoryGirl.create(:user) set_session_for(@user) fill_project - get :archive, @params + get :archive, @params.merge(:format => 'tar') 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 fe1028f67..4bb6f59b1 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -73,7 +73,7 @@ end describe Projects::IssuesController do before(:each) do - stub_rsync_methods + stub_symlink_methods @project = FactoryGirl.create(:project) @issue_user = FactoryGirl.create(:user) diff --git a/spec/controllers/projects/projects_controller_spec.rb b/spec/controllers/projects/projects_controller_spec.rb index 4893709f2..eace34aa2 100644 --- a/spec/controllers/projects/projects_controller_spec.rb +++ b/spec/controllers/projects/projects_controller_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' describe Projects::ProjectsController do before(:each) do - stub_rsync_methods + stub_symlink_methods @project = FactoryGirl.create(:project) @another_user = FactoryGirl.create(:user) diff --git a/spec/controllers/projects/subscribes_controller_spec.rb b/spec/controllers/projects/subscribes_controller_spec.rb index ea6c9b5af..8d37bb90d 100644 --- a/spec/controllers/projects/subscribes_controller_spec.rb +++ b/spec/controllers/projects/subscribes_controller_spec.rb @@ -49,7 +49,7 @@ end describe Projects::SubscribesController do before(:each) do - stub_rsync_methods + stub_symlink_methods @project = FactoryGirl.create(:project) @issue = FactoryGirl.create(:issue, :project_id => @project.id) diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb index 74b266789..f04c5e494 100644 --- a/spec/controllers/search_controller_spec.rb +++ b/spec/controllers/search_controller_spec.rb @@ -16,7 +16,7 @@ shared_examples_for 'not able search' do end describe SearchController do - before { stub_rsync_methods } + before { stub_symlink_methods } context 'as guest' do if APP_CONFIG['anonymous_access'] diff --git a/spec/controllers/users/profile_controller_spec.rb b/spec/controllers/users/profile_controller_spec.rb index 3fb73e1f0..0451de6a8 100644 --- a/spec/controllers/users/profile_controller_spec.rb +++ b/spec/controllers/users/profile_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Users::ProfileController do before(:each) do - stub_rsync_methods + stub_symlink_methods @simple_user = FactoryGirl.create(:user) @other_user = FactoryGirl.create(:user) @@ -27,7 +27,7 @@ describe Users::ProfileController do end it 'should be able to view profile' do - get :show, :owner_name => @other_user.uname + get :show, :uname => @other_user.uname response.code.should eq('200') end diff --git a/spec/factories/arches.rb b/spec/factories/arches.rb index e72251a9d..eb210cbd0 100644 --- a/spec/factories/arches.rb +++ b/spec/factories/arches.rb @@ -1,6 +1,6 @@ # -*- encoding : utf-8 -*- FactoryGirl.define do factory :arch do - name { FactoryGirl.generate(:string) } + name { FactoryGirl.generate(:unixname) } end end diff --git a/spec/factories/build_lists.rb b/spec/factories/build_lists.rb index f48df51a8..88dda9c27 100644 --- a/spec/factories/build_lists.rb +++ b/spec/factories/build_lists.rb @@ -3,13 +3,13 @@ FactoryGirl.define do factory :build_list do association :user association :project - association :pl, :factory => :platform_with_repos + association :save_to_platform, :factory => :platform_with_repos association :arch - bpl {|bl| bl.pl} + build_for_platform {|bl| bl.save_to_platform} project_version "1.0" build_requires true update_type 'security' - include_repos {|bl| bl.pl.repositories.map(&:id)} + include_repos {|bl| bl.save_to_platform.repositories.map(&:id)} commit_hash '1234567890abcdef1234567890abcdef12345678' end diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb index b02165f4c..7c350c58e 100644 --- a/spec/mailers/user_mailer_spec.rb +++ b/spec/mailers/user_mailer_spec.rb @@ -6,7 +6,7 @@ describe UserMailer do context 'On Issue create' do before(:each) do - stub_rsync_methods + stub_symlink_methods @project = FactoryGirl.create(:project) @issue_user = FactoryGirl.create(:user) @@ -44,7 +44,7 @@ describe UserMailer do context 'On Issue assign' do before(:each) do - stub_rsync_methods + stub_symlink_methods @project = FactoryGirl.create(:project) @issue_user = FactoryGirl.create(:user) @@ -80,7 +80,7 @@ describe UserMailer do context 'On Comment create' do before(:each) do - stub_rsync_methods + stub_symlink_methods @project = FactoryGirl.create(:project) @issue_user = FactoryGirl.create(:user) diff --git a/spec/models/advisory_spec.rb b/spec/models/advisory_spec.rb new file mode 100644 index 000000000..abbb38c8e --- /dev/null +++ b/spec/models/advisory_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe Advisory do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/cancan_spec.rb b/spec/models/cancan_spec.rb index d2317f33b..c496fbbf9 100644 --- a/spec/models/cancan_spec.rb +++ b/spec/models/cancan_spec.rb @@ -25,7 +25,7 @@ describe CanCan do let(:register_request) { FactoryGirl.create(:register_request) } before(:each) do - stub_rsync_methods + stub_symlink_methods end context 'Site admin' do @@ -94,7 +94,9 @@ describe CanCan do end end - it { @ability.should be_able_to(:show, User) } + it "shoud be able to show user profile" do + @ability.should be_able_to(:show, User) + end it "shoud be able to read another user object" do admin_create diff --git a/spec/models/comment_for_commit_spec.rb b/spec/models/comment_for_commit_spec.rb index ac9a0743f..181859d56 100644 --- a/spec/models/comment_for_commit_spec.rb +++ b/spec/models/comment_for_commit_spec.rb @@ -23,7 +23,7 @@ def set_comments_data_for_commit end describe Comment do - before { stub_rsync_methods } + before { stub_symlink_methods } context 'for global admin user' do before(:each) do @user = FactoryGirl.create(:admin) diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb index 16caf891b..afc99e0bc 100644 --- a/spec/models/comment_spec.rb +++ b/spec/models/comment_spec.rb @@ -15,7 +15,7 @@ def set_commentable_data end describe Comment do - before { stub_rsync_methods } + before { stub_symlink_methods } context 'for global admin user' do before(:each) do @user = FactoryGirl.create(:admin) diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index e45a47994..36209c472 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -4,7 +4,7 @@ require "cancan/matchers" describe Group do before(:each) do - stub_rsync_methods + stub_symlink_methods @group = FactoryGirl.create(:group) @ability = Ability.new(User.new) end diff --git a/spec/models/platform_spec.rb b/spec/models/platform_spec.rb index bb780e03f..8e4486144 100644 --- a/spec/models/platform_spec.rb +++ b/spec/models/platform_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Platform do before(:all) do - stub_rsync_methods + stub_symlink_methods Platform.delete_all User.delete_all FileUtils.rm_rf(APP_CONFIG['root_path']) @@ -18,7 +18,7 @@ describe Platform do it { should validate_presence_of(:name)} it { should validate_uniqueness_of(:name).case_insensitive } - it { should validate_format_of(:name).with('Basic_platfrom-name-1234') } + it { should validate_format_of(:name).with('Basic_platform-name-1234') } it { should validate_format_of(:name).not_with('.!') } it { should validate_presence_of(:description) } it { should validate_presence_of(:distrib_type) } diff --git a/spec/models/product_build_list_spec.rb b/spec/models/product_build_list_spec.rb index 9394cf8af..76587112f 100644 --- a/spec/models/product_build_list_spec.rb +++ b/spec/models/product_build_list_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe ProductBuildList do before(:all) do - stub_rsync_methods + stub_symlink_methods end it { should belong_to(:product) } diff --git a/spec/models/product_spec.rb b/spec/models/product_spec.rb index d8638a23d..d8068fae6 100644 --- a/spec/models/product_spec.rb +++ b/spec/models/product_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Product do before(:all) do - stub_rsync_methods + stub_symlink_methods Platform.delete_all User.delete_all Product.delete_all diff --git a/spec/models/project_to_repository_spec.rb b/spec/models/project_to_repository_spec.rb index d79c0fe02..8bde7bb95 100644 --- a/spec/models/project_to_repository_spec.rb +++ b/spec/models/project_to_repository_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe ProjectToRepository do before(:each) do - stub_rsync_methods + stub_symlink_methods @platform = FactoryGirl.create(:platform) @first_repo = FactoryGirl.create(:repository, :platform_id => @platform.id) @second_repo = FactoryGirl.create(:repository, :platform_id => @platform.id) diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 57322ebdb..559507b2d 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -5,7 +5,7 @@ describe Repository do context 'when create with same owner that platform' do before (:each) do - stub_rsync_methods + stub_symlink_methods @platform = FactoryGirl.create(:platform) @params = {:name => 'tst_platform', :description => 'test platform'} end @@ -17,7 +17,7 @@ describe Repository do end before(:all) do - stub_rsync_methods + stub_symlink_methods Platform.delete_all User.delete_all Repository.delete_all diff --git a/spec/models/subscribe_spec.rb b/spec/models/subscribe_spec.rb index be111a6a8..a74be8a0d 100644 --- a/spec/models/subscribe_spec.rb +++ b/spec/models/subscribe_spec.rb @@ -12,7 +12,7 @@ def set_testable_data end describe Subscribe do - before { stub_rsync_methods } + before { stub_symlink_methods } context 'for global admin user' do before(:each) do @user = FactoryGirl.create(:admin) diff --git a/spec/routing/projects_routing_spec.rb.rb b/spec/routing/projects_routing_spec.rb.rb new file mode 100644 index 000000000..ac8d5d2e2 --- /dev/null +++ b/spec/routing/projects_routing_spec.rb.rb @@ -0,0 +1,46 @@ +# -*- encoding : utf-8 -*- +require "spec_helper" + +describe Projects::ProjectsController do + describe "routing" do + + it "routes to #index" do + get("/projects").should route_to("projects/projects#index") + end + + it "routes to #new" do + get("/projects/new").should route_to("projects/projects#new") + end + + it "routes to #edit" do + get("/import/glib2.0-mib/edit").should route_to("projects/projects#edit", :owner_name => 'import', :project_name => 'glib2.0-mib') + end + + it "routes to #create" do + post("/projects").should route_to("projects/projects#create") + end + + it "routes to #update" do + put("/import/glib2.0-mib").should route_to("projects/projects#update", :owner_name => 'import', :project_name => 'glib2.0-mib') + end + + it "routes to #destroy" do + delete("/import/glib2.0-mib").should route_to("projects/projects#destroy", :owner_name => 'import', :project_name => 'glib2.0-mib') + end + + end +end + +describe Projects::Git::TreesController do + describe "routing" do + + it "routes to #show" do + get("/import/glib2.0-mib").should route_to("projects/git/trees#show", :owner_name => 'import', :project_name => 'glib2.0-mib') + get("/import/glib2.0-mib/tree/branch").should route_to("projects/git/trees#show", :owner_name => 'import', :project_name => 'glib2.0-mib', :treeish => 'branch') + get("/import/glib2.0-mib/tree/branch/some/path.to").should route_to("projects/git/trees#show", :owner_name => 'import', :project_name => 'glib2.0-mib', :treeish => 'branch', :path => 'some/path.to') + end + + # TODO write more specs also with slash in branch name! + + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b941cc318..7eab2ddcd 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -33,9 +33,9 @@ def set_session_for(user=nil) sign_in current_user end -def stub_rsync_methods - any_instance_of(Platform, :mount_directory_for_rsync => true) - any_instance_of(Platform, :umount_directory_for_rsync => true) +def stub_symlink_methods + any_instance_of(Platform, :symlink_directory => true) + any_instance_of(Platform, :remove_symlink_directory => true) end def test_git_commit(project) diff --git a/vendor/assets/images/pirobox/bottom_nav.png b/vendor/assets/images/pirobox/bottom_nav.png new file mode 100644 index 000000000..31478f682 Binary files /dev/null and b/vendor/assets/images/pirobox/bottom_nav.png differ diff --git a/vendor/assets/images/pirobox/caption.png b/vendor/assets/images/pirobox/caption.png new file mode 100644 index 000000000..b9cd20122 Binary files /dev/null and b/vendor/assets/images/pirobox/caption.png differ diff --git a/vendor/assets/images/pirobox/close.png b/vendor/assets/images/pirobox/close.png new file mode 100644 index 000000000..062be9e00 Binary files /dev/null and b/vendor/assets/images/pirobox/close.png differ diff --git a/vendor/assets/images/pirobox/loadinfo.gif b/vendor/assets/images/pirobox/loadinfo.gif new file mode 100644 index 000000000..40fb9cf46 Binary files /dev/null and b/vendor/assets/images/pirobox/loadinfo.gif differ diff --git a/vendor/assets/images/pirobox/new_skin.png b/vendor/assets/images/pirobox/new_skin.png new file mode 100644 index 000000000..36b85af9d Binary files /dev/null and b/vendor/assets/images/pirobox/new_skin.png differ diff --git a/vendor/assets/images/pirobox/new_skin_left.png b/vendor/assets/images/pirobox/new_skin_left.png new file mode 100644 index 000000000..9e515ec58 Binary files /dev/null and b/vendor/assets/images/pirobox/new_skin_left.png differ diff --git a/vendor/assets/images/pirobox/new_skin_top.png b/vendor/assets/images/pirobox/new_skin_top.png new file mode 100644 index 000000000..28499ab68 Binary files /dev/null and b/vendor/assets/images/pirobox/new_skin_top.png differ diff --git a/vendor/assets/images/pirobox/next.png b/vendor/assets/images/pirobox/next.png new file mode 100644 index 000000000..f39aacaac Binary files /dev/null and b/vendor/assets/images/pirobox/next.png differ diff --git a/vendor/assets/images/pirobox/prev.png b/vendor/assets/images/pirobox/prev.png new file mode 100644 index 000000000..60aebdb17 Binary files /dev/null and b/vendor/assets/images/pirobox/prev.png differ diff --git a/vendor/assets/javascripts/pirobox_extended_min.js b/vendor/assets/javascripts/pirobox_extended_min.js new file mode 100644 index 000000000..cf7a90ea9 --- /dev/null +++ b/vendor/assets/javascripts/pirobox_extended_min.js @@ -0,0 +1,33 @@ +/** +* Name: PiroBox Extended v.1.0 +* Date: Gen 2011 +* Autor: Diego Valobra (http://www.pirolab.it),(http://www.diegovalobra.com) +* Version: 1.0 +* Licence: CC-BY-SA http://creativecommons.org/licenses/by-sa/3/it/ +**/ +(function($){$.fn.piroBox_ext=function(opt){opt=jQuery.extend({piro_speed:700,bg_alpha:0.9,piro_scroll:true},opt);$.fn.piroFadeIn=function(speed,callback){$(this).fadeIn(speed,function(){if(jQuery.browser.msie) +$(this).get(0).style.removeAttribute('filter');if(callback!=undefined) +callback();});};$.fn.piroFadeOut=function(speed,callback){$(this).fadeOut(speed,function(){if(jQuery.browser.msie) +$(this).get(0).style.removeAttribute('filter');if(callback!=undefined) +callback();});};var my_gall_obj=$('a[class*="pirobox"]');var map=new Object();for(var i=0;i'+''+''+''+''+''+''+''+''+''+''+''+''+''+''+''+''+'
'+'
'+'
'+''+'
'+'
'+'
'+'
');$('body').append(struct);var wrapper=$('.piro_html'),piro_capt=$('.caption'),piro_bg=$('.piro_overlay'),piro_next=$('.piro_next'),piro_prev=$('.piro_prev'),piro_next_fake=$('.piro_next_fake'),piro_prev_fake=$('.piro_prev_fake'),piro_close=$('.piro_close'),div_reg=$('.div_reg'),piro_loader=$('.piro_loader'),resize=$('.resize'),btn_info=$('.btn_info');var rz_img=0.95;if($.browser.msie){wrapper.draggable({handle:'.h_t_c,.h_b_c,.div_reg img'});}else{wrapper.draggable({handle:'.h_t_c,.h_b_c,.div_reg img',opacity:0.80});} +var y=$(window).height();var x=$(window).width();$('.nav_container').hide();wrapper.css({left:((x/2)-(250))+'px',top:parseInt($(document).scrollTop())+(100)});$(wrapper).add(piro_capt).add(piro_bg).hide();piro_bg.css({'opacity':opt.bg_alpha});$(piro_prev).add(piro_next).bind('click',function(c){$('.nav_container').hide();c.preventDefault();piro_next.add(piro_prev).hide();var obj_count=parseInt($('a[class*="pirobox_gall"]').filter('.item').attr('rev'));var start=$(this).is('.piro_prev')?$('a[class*="pirobox_gall"]').eq(obj_count-1):$('a[class*="pirobox_gall"]').eq(obj_count+1);start.click();});$('html').bind('keyup',function(c){if(c.keyCode==27){c.preventDefault();if($(piro_close).is(':visible')){close_all();}}});$('html').bind('keyup',function(e){if($('.item').is('.first')){}else if(e.keyCode==37){e.preventDefault();if($(piro_close).is(':visible')){piro_prev.click();}}});$('html').bind('keyup',function(z){if($('.item').is('.last')){}else if(z.keyCode==39){z.preventDefault();if($(piro_close).is(':visible')){piro_next.click();}}});$(window).resize(function(){var new_y=$(window).height();var new_x=$(window).width();var new_h=wrapper.height();var new_w=wrapper.width();wrapper.css({left:((new_x/2)-(new_w/2))+'px',top:parseInt($(document).scrollTop())+(new_y-new_h)/2});});function scrollIt(){$(window).scroll(function(){var new_y=$(window).height();var new_x=$(window).width();var new_h=wrapper.height();var new_w=wrapper.width();wrapper.css({left:((new_x/2)-(new_w/2))+'px',top:parseInt($(document).scrollTop())+(new_y-new_h)/2});});} +if(opt.piro_scroll==true){scrollIt()} +$(piro_gallery).each(function(){var descr=$(this).attr('title');var params=$(this).attr('rel').split('-');var p_link=$(this).attr('href');$(this).unbind();$(this).bind('click',function(e){piro_bg.css({'opacity':opt.bg_alpha});e.preventDefault();piro_next.add(piro_prev).hide().css('visibility','hidden');$(piro_gallery).filter('.item').removeClass('item');$(this).addClass('item');open_all();if($(this).is('.first')){piro_prev.hide();piro_next.show();piro_prev_fake.show().css({'opacity':0.5,'visibility':'hidden'});}else{piro_next.add(piro_prev).show();piro_next_fake.add(piro_prev_fake).hide();} +if($(this).is('.last')){piro_prev.show();piro_next_fake.show().css({'opacity':0.5,'visibility':'hidden'});piro_next.hide();} +if($(this).is('.pirobox')){piro_next.add(piro_prev).hide();}});function open_all(){wrapper.add(piro_bg).add(div_reg).add(piro_loader).show();function animate_html(){if(params[1]=='full'&¶ms[2]=='full'){params[2]=$(window).height()-70;params[1]=$(window).width()-55;} +var y=$(window).height();var x=$(window).width();piro_close.hide();div_reg.add(resize).animate({'height':+(params[2])+'px','width':+(params[1])+'px'},opt.piro_speed).css('visibility','visible');wrapper.animate({height:+(params[2])+20+'px',width:+(params[1])+20+'px',left:((x/2)-((params[1])/2+10))+'px',top:parseInt($(document).scrollTop())+(y-params[2])/2-10},opt.piro_speed,function(){piro_next.add(piro_prev).css({'height':'20px','width':'20px'});piro_next.add(piro_prev).add(piro_prev_fake).add(piro_next_fake).css('visibility','visible');$('.nav_container').show();piro_close.show();});} +function animate_image(){var img=new Image();img.onerror=function(){piro_capt.html('');img.src="http://www.pirolab.it/pirobox/js/error.jpg";} +img.onload=function(){piro_capt.add(btn_info).hide();var y=$(window).height();var x=$(window).width();var imgH=img.height;var imgW=img.width;if(imgH+20>y||imgW+20>x){var _x=(imgW+20)/x;var _y=(imgH+20)/y;if(_y>_x){imgW=Math.round(img.width*(rz_img/_y));imgH=Math.round(img.height*(rz_img/_y));}else{imgW=Math.round(img.width*(rz_img/_x));imgH=Math.round(img.height*(rz_img/_x));}}else{imgH=img.height;imgW=img.width;} +var y=$(window).height();var x=$(window).width();$(img).height(imgH).width(imgW).hide();$(img).fadeOut(300,function(){});$('.div_reg img').remove();$('.div_reg').html('');div_reg.append(img).show();$(img).addClass('immagine');div_reg.add(resize).animate({height:imgH+'px',width:imgW+'px'},opt.piro_speed);wrapper.animate({height:(imgH+20)+'px',width:(imgW+20)+'px',left:((x/2)-((imgW+20)/2))+'px',top:parseInt($(document).scrollTop())+(y-imgH)/2-20},opt.piro_speed,function(){var cap_w=resize.width();piro_capt.css({width:cap_w+'px'});piro_loader.hide();$(img).fadeIn(300,function(){piro_close.add(btn_info).show();piro_capt.slideDown(200);piro_next.add(piro_prev).css({'height':'20px','width':'20px'});piro_next.add(piro_prev).add(piro_prev_fake).add(piro_next_fake).css('visibility','visible');$('.nav_container').show();resize.resize(function(){NimgW=img.width;NimgH=img.heigh;piro_capt.css({width:(NimgW)+'px'});});});});} +img.src=p_link;piro_loader.click(function(){img.src='about:blank';});} +switch(params[0]){case'iframe':div_reg.html('').css('overflow','hidden');resize.css('overflow','hidden');piro_close.add(btn_info).add(piro_capt).hide();animate_html();div_reg.piroFadeIn(300,function(){div_reg.append('');$('.my_frame').css({'height':+(params[2])+'px','width':+(params[1])+'px'});piro_loader.hide();});break;case'content':div_reg.html('').css('overflow','auto');resize.css('overflow','auto');$('.my_frame').remove();piro_close.add(btn_info).add(piro_capt).hide();animate_html() +div_reg.piroFadeIn(300,function(){div_reg.load(p_link);piro_loader.hide();});break;case'inline':div_reg.html('').css('overflow','auto');resize.css('overflow','auto');$('.my_frame').remove();piro_close.add(btn_info).add(piro_capt).hide();animate_html() +div_reg.piroFadeIn(300,function(){$(p_link).clone(true).appendTo(div_reg).piroFadeIn(300);piro_loader.hide();});break +case'gallery':div_reg.css('overflow','hidden');resize.css('overflow','hidden');$('.my_frame').remove();piro_close.add(btn_info).add(piro_capt).hide();if(descr==""){piro_capt.html('');}else{piro_capt.html('

'+descr+'

');} +animate_image();break;case'single':piro_close.add(btn_info).add(piro_capt).hide();div_reg.html('').css('overflow','hidden');resize.css('overflow','hidden');$('.my_frame').remove();if(descr==""){piro_capt.html('');}else{piro_capt.html('

'+descr+'

');} +animate_image();break}}});$('.immagine').live('click',function(){piro_capt.slideToggle(200);});function close_all(){if($('.piro_close').is(':visible')){$('.my_frame').remove();wrapper.add(div_reg).add(resize).stop();var ie_sucks=wrapper;if($.browser.msie){ie_sucks=div_reg.add(piro_bg);$('.div_reg img').remove();}else{ie_sucks=wrapper.add(piro_bg);} +ie_sucks.piroFadeOut(200,function(){div_reg.html('');piro_loader.add(piro_capt).add(btn_info).hide();$('.nav_container').hide();piro_bg.add(wrapper).hide().css('visibility','visible');});}} +piro_close.add(piro_loader).add(piro_bg).bind('click',function(y){y.preventDefault();close_all();});}})(jQuery); \ No newline at end of file diff --git a/vendor/assets/stylesheets/pirobox.scss b/vendor/assets/stylesheets/pirobox.scss new file mode 100644 index 000000000..ceb4a69a6 --- /dev/null +++ b/vendor/assets/stylesheets/pirobox.scss @@ -0,0 +1,44 @@ +/* +*{ + margin:0; + padding:0; +}*/ +.piro_html {position:absolute; top:0; left:0; padding:0; width:500px; height: 500px; margin:0; display:block; padding:0; z-index:150001; padding:0; } +.piro_html table,.piro_html tbody,.piro_html tr,.piro_html th,.piro_html td{margin:0;padding:0;border:none;} +.piro_html img{ margin:0; padding:0; border:none;} + +.piro_html .h_t_l{ width:10px; height:10px; background: image-url('pirobox/new_skin.png') top left no-repeat;} +.piro_html .h_t_r{ width:10px; height:10px; background: image-url('pirobox/new_skin.png') top right no-repeat;} +.piro_html .h_t_c{ cursor:move; height:10px;background: image-url('pirobox/new_skin_top.png') top repeat-x;} + +.piro_html .h_c_l{width:10px; background: image-url('pirobox/new_skin_left.png') left repeat-y; } +.piro_html .h_c_c{background: image-url('pirobox/caption.png');margin:0; padding:0;} +.piro_html .h_c_c .div_reg{ background: image-url('pirobox/caption.png'); width:480px; overflow:hidden; height:480px; margin:0; padding:0; } +.piro_html .h_c_c .div_reg img{ cursor:move;} +.piro_html .h_c_r{width:10px; background: image-url('pirobox/new_skin_left.png') right repeat-y;} + +.piro_html .h_b_c{ cursor:move; height:10px;background: image-url('pirobox/new_skin_top.png') bottom repeat-x;} +.piro_html .h_b_l{ width:10px; height:10px;background: image-url('pirobox/new_skin.png') bottom left no-repeat;} +.piro_html .h_b_r{ width:10px; height:10px;background: image-url('pirobox/new_skin.png') bottom right no-repeat;} + +.piro_overlay{position:fixed; top:0; left:0; width:100%; height:100%; z-index:150000;background:#fff;display:none; cursor:pointer;} +.piro_loader{position:absolute;top:50%;left:50%;margin:-59px 0 0 -59px;width:118px;height:118px;display:block;z-index:150005; cursor:pointer; } +.piro_loader span{position:absolute;top:50%;left:50%;margin-top:-36px;margin-left:-36px;width:72px;height:72px;display:block;z-index:150009; background: image-url('pirobox/loadinfo.gif') center top no-repeat; } +.piro_title{position:fixed; background: image-url('pirobox/bg_title.png') bottom repeat-x;top:0;left:0;width:100%; text-align:center;display:block; padding:6px 0 10px 0; color:white; z-index:150000; font-size:18px; display:none;} +.btn_info{position:absolute;bottom:-7px;right:-7px;width:25px; height:25px;margin:0;display:block; padding:0px; color:black; cursor:pointer; background: image-url('pirobox/b_w/info.png') no-repeat; z-index:1500440} +.caption{position:absolute;bottom:10px;left:10px;margin:0;display:block; padding:0px; color:black; cursor:text; background: image-url('pirobox/caption.png'); z-index:150018} +.caption p{ display:block; margin:0;padding:7px 5px; text-align:center; font-weight:normal; font-size:14px; color:white; z-index:150019; color:white;} + +.nav_container{position:absolute; right:5px; bottom:-20px; height:25px; width:60px; background: image-url('pirobox/bottom_nav.png') bottom; z-index:1500190000000;} +.piro_close{position:absolute;right:20px; top:0;height:20px;width:20px;background: transparent image-url('pirobox/close.png') no-repeat center center;cursor:pointer;margin:0 0 0 0;z-index:150022;display:none;} +a.piro_next{position:absolute;width:20px; top:0; right:0px; height:20px;text-indent:-999em;outline:none; display:block; margin:0;background:image-url('pirobox/next.png') center right no-repeat; border:none; cursor:pointer;z-index:150023} +a:hover.piro_next{background:image-url('pirobox/next.png') center right no-repeat;} +.piro_next_fake{position:absolute;width:20px; top:0;right:0px; height:20px;outline:none; text-indent:-999em; display:none; margin:0;background: image-url('pirobox/next.png') center right no-repeat; border:none; cursor:auto;z-index:150020} +.piro_prev_fake{position:absolute;width:20px; top:0;right:40px; height:20px;outline:none; text-indent:-999em; display:none; margin:0;background: image-url('pirobox/prev.png') center right no-repeat; border:none; cursor:auto;z-index:150020} + +a.piro_prev{position:absolute;width:20px; right:40px; top:0; height:20px; text-indent:-999em; outline:none;display:block;margin:0;background: image-url('pirobox/prev.png') center left no-repeat;border:none; cursor:pointer; z-index:150024} +a:hover.piro_prev{background:image-url('pirobox/prev.png') center left no-repeat;} +a.close_pirobox{color:#bb0f05;} + + +