Merge branch 'master' into 90-pull

Conflicts:
	app/assets/stylesheets/design/custom.scss
	config/locales/title.en.yml
	config/locales/title.ru.yml
	config/routes.rb
	db/schema.rb
This commit is contained in:
Alexander Machehin 2012-05-17 22:58:29 +06:00
commit fcffff4178
142 changed files with 1800 additions and 351 deletions

View File

@ -71,6 +71,7 @@ group :development do
gem 'shotgun' gem 'shotgun'
# deploy # deploy
gem 'capistrano', :require => false gem 'capistrano', :require => false
gem 'rvm-capistrano', :require => false
gem 'cape', :require => false gem 'cape', :require => false
gem 'capistrano_colors', :require => false gem 'capistrano_colors', :require => false
end end

View File

@ -255,6 +255,8 @@ GEM
ruby-openid (2.1.8) ruby-openid (2.1.8)
russian (0.6.0) russian (0.6.0)
i18n (>= 0.5.0) i18n (>= 0.5.0)
rvm-capistrano (1.1.0)
capistrano (>= 2.0.0)
sanitize (2.0.3) sanitize (2.0.3)
nokogiri (>= 1.4.4, < 1.6) nokogiri (>= 1.4.4, < 1.6)
sass (3.1.16) sass (3.1.16)
@ -358,6 +360,7 @@ DEPENDENCIES
rspec-rails (~> 2.9.0) rspec-rails (~> 2.9.0)
ruby-haml-js (~> 0.0.3) ruby-haml-js (~> 0.0.3)
russian (~> 0.6.0) russian (~> 0.6.0)
rvm-capistrano
sass-rails (~> 3.2.5) sass-rails (~> 3.2.5)
shotgun shotgun
shoulda shoulda

BIN
app/assets/images/rss.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

@ -1,5 +1,5 @@
$(document).ready(function() { $(document).ready(function() {
$('#build_list_pl_id').change(function() { $('#build_list_save_to_platform_id').change(function() {
var platform_id = $(this).val(); var platform_id = $(this).val();
var base_platforms = $('.all_platforms input[type=checkbox].build_bpl_ids'); 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).attr('checked', 'checked').removeAttr('disabled').trigger('change');
$(this).parent().find('.offset25 input[type="checkbox"]').removeAttr('disabled'); $(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') { if (rep_name != 'main') {
$(this).parent().find('.offset25 input[type="checkbox"][rep_name="' + rep_name + '"]').attr('checked', 'checked'); $(this).parent().find('.offset25 input[type="checkbox"][rep_name="' + rep_name + '"]').attr('checked', 'checked');
} }
@ -33,7 +33,7 @@ $(document).ready(function() {
setBranchSelected(); setBranchSelected();
}); });
$('#build_list_pl_id').trigger('change'); $('#build_list_save_to_platform_id').trigger('change');
$('.offset25 label').click(function() { $('.offset25 label').click(function() {
setPlChecked($(this).prev()[0], !$(this).prev().attr('checked')); setPlChecked($(this).prev()[0], !$(this).prev().attr('checked'));
@ -58,10 +58,10 @@ function setPlChecked(pointer, checked) {
} }
function setBranchSelected() { 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: // Checks if selected platform is main or not:
if ( $('.all_platforms').find('input[type="checkbox"][value=' + pl_id + '].build_bpl_ids').size() > 0 ) { 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 + '"]'); var branch_pl_opt = $('#build_list_project_version option[value="latest_' + pl_name + '"]');
// If there is branch we need - set it selected: // If there is branch we need - set it selected:
if ( branch_pl_opt.size() > 0 ) { if ( branch_pl_opt.size() > 0 ) {

View File

@ -0,0 +1,3 @@
//= require jquery
//= require jquery-ui
//= require pirobox_extended_min

View File

@ -456,6 +456,18 @@ table.tablesorter.platforms .th2 {
width: 280px; 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 { table.tablesorter tr td.buttons {
text-align: center; text-align: center;
} }
@ -922,6 +934,16 @@ div#git_help_data p {
background: none repeat scroll 0 0; background: none repeat scroll 0 0;
} }
.font14 { .rightlist p {
font-size: 14px; padding-bottom: 1em;
}
.leftlist span.hint {
padding-top: 1em;
display: block;
font-size: 0.9em;
}
.atom_icon {
vertical-align: top;
} }

View File

@ -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;
}

View File

@ -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

View File

@ -21,7 +21,8 @@ class ApplicationController < ActionController::Base
protected protected
def set_locale 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 end
def get_user_locale def get_user_locale

View File

@ -6,7 +6,7 @@ class Groups::BaseController < ApplicationController
protected protected
def find_group 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 @group = Group.find_by_insensitive_uname! group_id
end end
end end

View File

@ -4,6 +4,19 @@ class PagesController < ApplicationController
# load_and_authorize_resource # load_and_authorize_resource
def root 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 end
def forbidden def forbidden

View File

@ -7,7 +7,7 @@ class Projects::BuildListsController < Projects::BaseController
before_filter :authenticate_build_service!, :only => CALLBACK_ACTIONS before_filter :authenticate_build_service!, :only => CALLBACK_ACTIONS
skip_before_filter :authenticate_user!, :only => [:show, :index, :search] if APP_CONFIG['anonymous_access'] skip_before_filter :authenticate_user!, :only => [:show, :index, :search] 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] 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 load_and_authorize_resource :project, :only => NESTED_ACTIONS
@ -40,16 +40,16 @@ class Projects::BuildListsController < Projects::BaseController
def create def create
notices, errors = [], [] 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 params[:build_list][:auto_publish] = false if @platform.released
Arch.where(:id => params[:arches]).each do |arch| 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 = @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.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.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.bpl.repository_ids.include? ir.to_i} @build_list.include_repos = @build_list.include_repos.select {|ir| @build_list.build_for_platform.repository_ids.include? ir.to_i}
@build_list.priority = 100 # User builds more priority than mass rebuild with zero priority @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, :bpl => bpl.name, :pl => @build_list.pl} flash_options = {:project_version => @build_list.project_version, :arch => arch.name, :build_for_platform => build_for_platform.name}
if @build_list.save if @build_list.save
notices << t("flash.build_list.saved", flash_options) notices << t("flash.build_list.saved", flash_options)
else else
@ -72,19 +72,14 @@ class Projects::BuildListsController < Projects::BaseController
@item_groups = @build_list.items.group_by_level @item_groups = @build_list.items.group_by_level
end end
def publish def update
if @build_list.publish if params[:publish].present? and can?(:publish, @build_list)
redirect_to :back, :notice => t('layout.build_lists.publish_success') publish
elsif params[:reject_publish].present? and can?(:reject_publish)
reject_publish
else else
redirect_to :back, :notice => t('layout.build_lists.publish_fail') # King Arthur, we are under attack!
end redirect_to :forbidden and return
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 end
@ -117,6 +112,8 @@ class Projects::BuildListsController < Projects::BaseController
@build_list.container_path = params[:container_path] @build_list.container_path = params[:container_path]
@build_list.save @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 render :nothing => true, :status => 200
end end
@ -172,4 +169,29 @@ class Projects::BuildListsController < Projects::BaseController
render :nothing => true, :status => 403 render :nothing => true, :status => 403
end end
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 end

View File

@ -6,7 +6,7 @@ class Users::BaseController < ApplicationController
protected protected
def find_user 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 @user = User.find_by_insensitive_uname! user_id
end end
end end

View File

@ -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

View File

@ -17,7 +17,12 @@ module ApplicationHelper
end end
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 def title_object object
return object.advisory_id if object.class == Advisory
name = object.class == Group ? object.uname : object.name name = object.class == Group ? object.uname : object.name
object_name = t "activerecord.models.#{object.class.name.downcase}" object_name = t "activerecord.models.#{object.class.name.downcase}"
case object.class.name case object.class.name

View File

@ -5,7 +5,7 @@ module PlatformsHelper
return platform.released ? '/update' : '/release' return platform.released ? '/update' : '/release'
end end
def platfrom_printed_name(platform) def platform_printed_name(platform)
return "" unless platform return "" unless platform
platform.released? ? "#{platform.name} #{I18n.t("layout.platforms.released_suffix")}" : platform.name platform.released? ? "#{platform.name} #{I18n.t("layout.platforms.released_suffix")}" : platform.name
end end

View File

@ -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 => 'User', :owner_id => user.id}
can [:read, :related], BuildList, :project => {:owner_type => 'Group', :owner_id => user.group_ids} 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(: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| 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 end
can(:reject_publish, BuildList) do |build_list| 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 end
can(:cancel, BuildList) {|build_list| build_list.can_cancel? && can?(:write, build_list.project)} 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, :members], Platform, :visibility => 'open'
can [:read, :owned, :related, :members], Platform, :owner_type => 'User', :owner_id => user.id can [:read, :owned, :related, :members], Platform, :owner_type => 'User', :owner_id => user.id
can [:read, :related, :members], Platform, :owner_type => 'Group', :owner_id => user.group_ids can [:read, :related, :members], Platform, :owner_type => 'Group', :owner_id => user.group_ids

23
app/models/advisory.rb Normal file
View File

@ -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%<type>s-%<year>d:%<id>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

View File

@ -2,20 +2,28 @@
class BuildList < ActiveRecord::Base class BuildList < ActiveRecord::Base
belongs_to :project belongs_to :project
belongs_to :arch belongs_to :arch
belongs_to :pl, :class_name => 'Platform' belongs_to :save_to_platform, :class_name => 'Platform'
belongs_to :bpl, :class_name => 'Platform' belongs_to :build_for_platform, :class_name => 'Platform'
belongs_to :user belongs_to :user
belongs_to :advisory
has_many :items, :class_name => "BuildList::Item", :dependent => :destroy 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 :project_id, :project_version, :arch, :include_repos, :presence => true
validates_numericality_of :priority, :greater_than_or_equal_to => 0 validates_numericality_of :priority, :greater_than_or_equal_to => 0
validates :update_type, :inclusion => UPDATE_TYPES,
UPDATE_TYPES = %w[security bugfix enhancement recommended newpackage] :unless => Proc.new { |b| b.save_to_platform.released }
validates :update_type, :inclusion => UPDATE_TYPES validates :update_type, :inclusion => RELEASE_UPDATE_TYPES,
:if => Proc.new { |b| b.save_to_platform.released }
validate lambda { 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 # The kernel does not send these statuses directly
BUILD_CANCELED = 5000 BUILD_CANCELED = 5000
WAITING_FOR_RESPONSE = 4000 WAITING_FOR_RESPONSE = 4000
@ -62,7 +70,6 @@ class BuildList < ActiveRecord::Base
} }
scope :recent, order("#{table_name}.updated_at DESC") scope :recent, order("#{table_name}.updated_at DESC")
scope :for_status, lambda {|status| where(:status => status) } scope :for_status, lambda {|status| where(:status => status) }
scope :for_user, lambda { |user| where(:user_id => user.id) } scope :for_user, lambda { |user| where(:user_id => user.id) }
scope :scoped_to_arch, lambda {|arch| where(:arch_id => arch) } scope :scoped_to_arch, lambda {|arch| where(:arch_id => arch) }
@ -81,6 +88,7 @@ class BuildList < ActiveRecord::Base
s s
} }
scope :scoped_to_project_name, lambda {|project_name| joins(:project).where('projects.name LIKE ?', "%#{project_name}%")} 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 :additional_repos
serialize :include_repos serialize :include_repos
@ -106,6 +114,13 @@ class BuildList < ActiveRecord::Base
end end
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 def publish
return false unless can_publish? return false unless can_publish?
has_published = BuildServer.publish_container bs_id has_published = BuildServer.publish_container bs_id
@ -123,7 +138,7 @@ class BuildList < ActiveRecord::Base
end end
def can_reject_publish? def can_reject_publish?
can_publish? and pl.released can_publish? and save_to_platform.released
end end
def cancel def cancel
@ -159,7 +174,8 @@ class BuildList < ActiveRecord::Base
#[WAITING_FOR_RESPONSE, BuildServer::BUILD_PENDING, BuildServer::BUILD_STARTED].include?(status) #[WAITING_FOR_RESPONSE, BuildServer::BUILD_PENDING, BuildServer::BUILD_STARTED].include?(status)
end end
private protected
def set_default_status def set_default_status
self.status = WAITING_FOR_RESPONSE unless self.status.present? self.status = WAITING_FOR_RESPONSE unless self.status.present?
return true return true
@ -167,10 +183,17 @@ class BuildList < ActiveRecord::Base
def place_build def place_build
#XML-RPC params: project_name, project_version, plname, arch, bplname, update_type, build_requires, id_web, include_repos, priority #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 = 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 self.status = BUILD_PENDING if self.status == 0
save save
end end
#handle_asynchronously :place_build
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 end

View File

@ -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

View File

@ -13,6 +13,10 @@ class Platform < ActiveRecord::Base
has_many :actors, :as => :target, :class_name => 'Relation', :dependent => :destroy has_many :actors, :as => :target, :class_name => 'Relation', :dependent => :destroy
has_many :members, :through => :actors, :source => :actor, :source_type => 'User' 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 :description, :presence => true
validates :visibility, :presence => true, :inclusion => {:in => VISIBILITIES} validates :visibility, :presence => true, :inclusion => {:in => VISIBILITIES}
validates :name, :uniqueness => {:case_sensitive => false}, :presence => true, :format => { :with => /^[a-zA-Z0-9_\-]+$/ } validates :name, :uniqueness => {:case_sensitive => false}, :presence => true, :format => { :with => /^[a-zA-Z0-9_\-]+$/ }
@ -24,8 +28,9 @@ class Platform < ActiveRecord::Base
after_update :freeze_platform after_update :freeze_platform
after_create lambda { mount_directory_for_rsync unless hidden? } after_create lambda { symlink_directory unless hidden? }
after_destroy lambda { umount_directory_for_rsync unless hidden? } after_destroy lambda { remove_symlink_directory unless hidden? }
after_update :update_owner_relation after_update :update_owner_relation
scope :search_order, order("CHAR_LENGTH(name) ASC") scope :search_order, order("CHAR_LENGTH(name) ASC")
@ -63,7 +68,7 @@ class Platform < ActiveRecord::Base
build_path(name) build_path(name)
end end
def mount_path def symlink_path
Rails.root.join("public", "downloads", name) Rails.root.join("public", "downloads", name)
end end
@ -119,10 +124,10 @@ class Platform < ActiveRecord::Base
def change_visibility def change_visibility
if !self.hidden? if !self.hidden?
self.update_attribute(:visibility, 'hidden') self.update_attribute(:visibility, 'hidden')
umount_directory_for_rsync remove_symlink_directory
else else
self.update_attribute(:visibility, 'open') self.update_attribute(:visibility, 'open')
mount_directory_for_rsync symlink_directory
end end
end end
@ -130,19 +135,17 @@ class Platform < ActiveRecord::Base
system("sudo mkdir -p -m 0777 #{path}") system("sudo mkdir -p -m 0777 #{path}")
end end
def mount_directory_for_rsync def symlink_directory
# umount_directory_for_rsync # TODO ignore errors # umount_directory_for_rsync # TODO ignore errors
system("sudo mkdir -p -m 0777 #{mount_path}") system("ln -s #{path} #{symlink_path}")
system("sudo mount --bind #{path} #{mount_path}")
Arch.all.each do |arch| 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" 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
end end
def umount_directory_for_rsync def remove_symlink_directory
system("sudo umount #{mount_path}") system("rm -Rf #{symlink_path}")
system("sudo rm -Rf #{mount_path}")
end end
def update_owner_relation def update_owner_relation

View File

@ -2,6 +2,7 @@
class Project < ActiveRecord::Base class Project < ActiveRecord::Base
VISIBILITIES = ['open', 'hidden'] VISIBILITIES = ['open', 'hidden']
MAX_OWN_PROJECTS = 32000 MAX_OWN_PROJECTS = 32000
NAME_REGEXP = /[a-zA-Z0-9_\-\+\.]+/
belongs_to :owner, :polymorphic => true, :counter_cache => :own_projects_count 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 :collaborators, :through => :relations, :source => :actor, :source_type => 'User'
has_many :groups, :through => :relations, :source => :actor, :source_type => 'Group' 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 validates :owner, :presence => true
validate { errors.add(:base, :can_have_less_or_equal, :count => MAX_OWN_PROJECTS) if owner.projects.size >= MAX_OWN_PROJECTS } 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) arch = Arch.find_by_name(arch) if arch.acts_like?(:string)
build_lists.create do |bl| build_lists.create do |bl|
bl.pl = platform bl.save_to_platform = platform
bl.bpl = platform bl.build_to_platform = platform
bl.update_type = 'newpackage' bl.update_type = 'newpackage'
bl.arch = arch bl.arch = arch
bl.project_version = "latest_#{platform.name}" bl.project_version = "latest_#{platform.name}"

View File

@ -1,5 +1,7 @@
-set_meta_tags :title => nil -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' =render 'list'
- content_for :sidebar, render('sidebar') - content_for :sidebar, render('sidebar')

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -0,0 +1,4 @@
- set_meta_tags :title => t('layout.advisories.list_header')
- render :partial => 'submenu'
= render :partial => 'list', :object => @advisories
= will_paginate @advisories

View File

@ -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');

View File

@ -1,5 +1,5 @@
-set_meta_tags :title => [title_object(@group), t('layout.groups.edit')] -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 = render "form", :f => f
.hr .hr
@ -9,7 +9,7 @@
.hr .hr
.leftside= t("layout.groups.delete_warning") .leftside= t("layout.groups.delete_warning")
.rightside .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 .both
- content_for :sidebar, render('sidebar') - content_for :sidebar, render('sidebar')

View File

@ -2,6 +2,6 @@
%ul %ul
- (collection = t which_menu).each do |base, title| - (collection = t which_menu).each do |base, title|
- if can? :index, base.to_s.classify.constantize - 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' - 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')

View File

@ -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
});
});

View File

@ -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

View File

@ -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' : ''

View File

@ -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

View File

@ -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

View File

@ -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?}

View File

@ -1,5 +1,5 @@
- content_for :submenu do - content_for :submenu do
- act = action_name.to_sym; contr = controller_name.to_sym - act = action_name.to_sym; contr = controller_name.to_sym
.left= platfrom_printed_name(@platform) .left= platform_printed_name(@platform)
%nav %nav
%ul %ul

View File

@ -6,5 +6,5 @@
%tbody %tbody
- @platforms.each do |platform| - @platforms.each do |platform|
%tr{:class => cycle("odd", "even")} %tr{:class => cycle("odd", "even")}
%td= link_to platfrom_printed_name(platform), platform_path(platform) %td= link_to platform_printed_name(platform), platform_path(platform)
%td= platform.distrib_type %td= platform.distrib_type

View File

@ -1,4 +1,4 @@
- platform.repositories.each do |repo| - platform.repositories.each do |repo|
.both .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 = label_tag "include_repos_#{repo.id}", repo.name

View File

@ -1,18 +1,17 @@
-set_meta_tags :title => [title_object(@project), t('layout.build_lists.new_header')] -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| = form_for [@project, @build_list], :html => { :class => :form, :method => :post } do |f|
%section.left %section.left
%h3= t("activerecord.attributes.build_list.bpl") %h3= t("activerecord.attributes.build_list.build_for_platform")
.all_platforms .all_platforms
- Platform.main.each do |pl| - Platform.main.each do |pl|
- if pl.repository_ids.size > 0 - if pl.repository_ids.size > 0
.both .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 = label_tag "bpls_#{pl.id}", pl.name
.offset25{:style => 'padding-left: 25px'} .offset25{:style => 'padding-left: 25px'}= render 'include_repos', :platform => pl
= render 'include_repos', :platform => pl
%section.right %section.right
%h3= t("activerecord.attributes.build_list.pl") %h3= t("activerecord.attributes.build_list.save_to_platform")
.lineForm= f.select :pl_id, @project.repositories.collect{|r| ["#{r.platform.name}/#{r.name}", r.platform.id]} .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") %h3= t("activerecord.attributes.build_list.project_version")
- if controller.action_name == 'new' - if controller.action_name == 'new'
.lineForm= f.select :project_version, @project.versions_for_group_select, :selected => "latest_" + @project.default_branch .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") %h3= t("activerecord.attributes.build_list.arch")
- Arch.recent.each do |arch| - Arch.recent.each do |arch|
.both .both
- if controller.action_name == 'new' = check_box_tag "arches[]", arch.id, (params[:arches]||[]).include?(arch.id.to_s) || controller.action_name == 'new', :id => "arches_#{arch.id}"
= 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}"
= label_tag "arches_#{arch.id}", arch.name = label_tag "arches_#{arch.id}", arch.name
%h3= t("activerecord.attributes.build_list.update_type") %h3= t("activerecord.attributes.build_list.update_type")
.lineForm= f.select :update_type, BuildList::UPDATE_TYPES .lineForm= f.select :update_type, BuildList::UPDATE_TYPES

View File

@ -4,67 +4,83 @@
%p= @build_list.human_status %p= @build_list.human_status
%p= @build_list.updated_at %p= @build_list.updated_at
.both .both
= form_for @build_list do |f|
%h3= t("layout.build_lists.main_data") %h3= t("layout.build_lists.main_data")
.leftside.width125= t("activerecord.attributes.build_list.container_path") .leftlist= t("activerecord.attributes.build_list.container_path")
.leftside .rightlist
- if @build_list.status == BuildList::BUILD_PUBLISHED - if @build_list.status == BuildList::BUILD_PUBLISHED
= t("layout.build_lists.container_published") = t("layout.build_lists.container_published")
- elsif @build_list.container_path.present? - elsif @build_list.container_path.present?
- container_url = "http://#{request.host_with_port}/downloads#{@build_list.container_path}" - container_url = "http://#{request.host_with_port}/downloads#{@build_list.container_path}"
= link_to container_url, container_url = link_to container_url, container_url
.both .both
.leftside.width125= t("activerecord.attributes.build_list.user") .leftlist= t("activerecord.attributes.build_list.user")
.leftside .rightlist
= link_to @build_list.user.try(:fullname), @build_list.user = link_to @build_list.user.try(:fullname), @build_list.user
.both .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) .leftlist= t("activerecord.attributes.build_list.build_for_platform")
= 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) .rightlist
.hr = link_to @build_list.build_for_platform.name, @build_list.build_for_platform
%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 .both
.leftside.width125= t("activerecord.attributes.build_list.pl") .leftlist= t("activerecord.attributes.build_list.save_to_platform")
.leftside .rightlist
= link_to @build_list.pl.name, @build_list.pl = link_to @build_list.save_to_platform.name, @build_list.save_to_platform
.both .both
.leftside.width125= t("activerecord.attributes.build_list.include_repos") .leftlist= t("activerecord.attributes.build_list.include_repos")
.leftside= (@build_list.include_repos||[]).map{|r| Repository.find(r).name}.join(', ') .rightlist= (@build_list.include_repos||[]).map{|r| Repository.find(r).name}.join(', ')
.both .both
.leftside.width125= t("activerecord.attributes.build_list.update_type") .leftlist= t("activerecord.attributes.build_list.update_type")
.leftside= @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 .both
.leftside.width125= t("activerecord.attributes.build_list.build_requires") .leftlist= t("activerecord.attributes.build_list.build_requires")
.leftside= @build_list.build_requires .rightlist= t("layout.#{@build_list.build_requires}_")
.both .both
.leftside.width125= t("activerecord.attributes.build_list.auto_publish") .leftlist= t("activerecord.attributes.build_list.auto_publish")
.leftside= @build_list.auto_publish .rightlist= t("layout.#{@build_list.auto_publish}_")
.both .both
.leftside.width125= t("activerecord.attributes.build_list.project_version") .leftlist= t("activerecord.attributes.build_list.project_version")
.leftside= @build_list.project_version .rightlist= @build_list.project_version
.both .both
.leftside.width125= t("activerecord.attributes.build_list.arch") .leftlist= t("activerecord.attributes.build_list.arch")
.leftside= @build_list.arch.name .rightlist= @build_list.arch.name
.both .both
.leftside.width125= t("activerecord.attributes.build_list.updated_at") .leftlist= t("activerecord.attributes.build_list.updated_at")
.leftside= @build_list.updated_at .rightlist= @build_list.updated_at
.both .both
.leftside.width125= t("activerecord.attributes.build_list.is_circle") .leftlist= t("activerecord.attributes.build_list.is_circle")
.leftside= t("layout.#{@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 .both
- if !@build_list.in_work? && @build_list.started_at - if !@build_list.in_work? && @build_list.started_at
%br %br
.leftside.width125 .leftlist
.leftside= @build_list.human_duration .rightlist= @build_list.human_duration
.both .both
- if @build_list.in_work? - if @build_list.in_work?
%br %br
.leftside.width125 .leftlist
.leftside .rightlist
= "#{@build_list.human_current_duration} / #{@build_list.project.human_average_build_time}" = "#{@build_list.human_current_duration} / #{@build_list.project.human_average_build_time}"
.both .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 .hr
%h3= t("layout.build_lists.items_header") %h3= t("layout.build_lists.items_header")
- if @item_groups.blank? - if @item_groups.blank?
@ -86,6 +102,25 @@
%td= item.human_status %td= item.human_status
.both .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 :javascript
$('article .all').addClass('bigpadding'); $('article .all').addClass('bigpadding');

View File

@ -1,7 +1,6 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
$:.unshift File.expand_path('.') require 'cape'
$:.unshift(File.expand_path('./lib', ENV['rvm_path'])) require 'capistrano_colors'
set :rvm_type, :user
set :default_environment, { set :default_environment, {
'LANG' => 'en_US.UTF-8' 'LANG' => 'en_US.UTF-8'
@ -34,10 +33,10 @@ set :scm, :git
set :repository, "git@github.com:warpc/rosa-build.git" set :repository, "git@github.com:warpc/rosa-build.git"
set :deploy_via, :remote_cache set :deploy_via, :remote_cache
require 'lib/recipes/nginx' require './lib/recipes/nginx'
require 'lib/recipes/unicorn' require './lib/recipes/unicorn'
require 'lib/recipes/bluepill' require './lib/recipes/bluepill'
require 'lib/recipes/delayed_job' require './lib/recipes/delayed_job'
namespace :deploy do namespace :deploy do
task :stub_xml_rpc do task :stub_xml_rpc do
@ -92,7 +91,6 @@ after "deploy:restart", "delayed_job:restart"
after "deploy:restart", "deploy:cleanup" after "deploy:restart", "deploy:cleanup"
require 'cape'
namespace :rake_tasks do namespace :rake_tasks do
Cape do Cape do
mirror_rake_tasks 'db:seeds' mirror_rake_tasks 'db:seeds'

View File

@ -62,7 +62,7 @@ Rosa::Application.configure do
config.assets.digest = true config.assets.digest = true
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) # 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 end
# require 'stub_xml_rpc' # require 'stub_xml_rpc'

View File

@ -4,6 +4,8 @@ en:
turned_on: on turned_on: on
turned_off: off turned_off: off
list: List
year: year year: year
enter_commit_message: Commit message enter_commit_message: Commit message

View File

@ -4,6 +4,8 @@ ru:
turned_on: включены turned_on: включены
turned_off: выключены turned_off: выключены
list: Список
year: год year: год
enter_commit_message: Сопровождающее сообщение enter_commit_message: Сопровождающее сообщение

View File

@ -8,6 +8,7 @@ en:
projects: Projects projects: Projects
build_lists: Task monitoring build_lists: Task monitoring
groups: Groups groups: Groups
advisories: Advisories
bottom_menu: bottom_menu:
copyright: ROSA Lab © 2012 copyright: ROSA Lab © 2012
about: About the company about: About the company

View File

@ -8,6 +8,7 @@ ru:
projects: Проекты projects: Проекты
build_lists: Мониторинг задач build_lists: Мониторинг задач
groups: Группы groups: Группы
advisories: Бюллетени
bottom_menu: bottom_menu:
copyright: ROSA Лаб. © 2012 copyright: ROSA Лаб. © 2012
about: О компании about: О компании

View File

@ -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

View File

@ -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: Ссылки

View File

@ -18,10 +18,8 @@ en:
additional_repos: Additional repositories additional_repos: Additional repositories
include_repos: Included repositories include_repos: Included repositories
created_at: Created on created_at: Created on
pl: Repository for package storage save_to_platform: Repository for package storage
pl_id: Repository for package storage build_for_platform: Platform
bpl: Platform
bpl_id: Platform
update_type: Update type update_type: Update type
build_requires: Build with all the required packages build_requires: Build with all the required packages
auto_publish: Automated publising auto_publish: Automated publising
@ -38,6 +36,12 @@ en:
version: Version version: Version
build_list: Build list build_list: Build list
build_list/package:
name: Name
fullname: Fullname
release: Release
version: Version
layout: layout:
build_lists: build_lists:
filter_header: Filter filter_header: Filter
@ -50,6 +54,7 @@ en:
project_name_search: Search by project name project_name_search: Search by project name
bs_id_not_set: Id has not been configured yet bs_id_not_set: Id has not been configured yet
items_header: Build items items_header: Build items
packages_header: Container data
no_items_data: No data no_items_data: No data
show: Show show: Show
cancel_success: 'Build canceled' cancel_success: 'Build canceled'
@ -62,9 +67,13 @@ en:
action: Action action: Action
new_header: New build new_header: New build
main_data: Main data main_data: Main data
human_current_duration: Build currently takes %{hours} h. %{minutes} min. human_current_duration: Build currently takes %{hours} h. %{minutes} min.
human_duration: Builded in %{hours} h. %{minutes} min. human_duration: Builded in %{hours} h. %{minutes} min.
attached_advisory: Attached advisory
create_advisory: Create new advisory
ownership: ownership:
header: Build list ownership header: Build list ownership
owned: My owned: My
@ -107,8 +116,8 @@ en:
flash: flash:
build_list: build_list:
saved: Build list for project version '%{project_version}', platform '%{bpl}' and architecture '%{arch}' has been created successfully 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 '%{bpl}' and architecture '%{arch}' could not been created 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_selected: Select any version of the project
no_project_version_found: Project version '%{project_version}' not found no_project_version_found: Project version '%{project_version}' not found
no_arch_or_platform_selected: At least one of architecture of platform must selected no_arch_or_platform_selected: At least one of architecture of platform must selected

View File

@ -18,10 +18,8 @@ ru:
additional_repos: Дополнительные репозитории additional_repos: Дополнительные репозитории
include_repos: Подключаемые репозитории include_repos: Подключаемые репозитории
created_at: Создан created_at: Создан
pl: Репозиторий для сохранения пакетов save_to_platform: Репозиторий для сохранения пакетов
pl_id: Репозиторий для сохранения пакетов build_for_platform: Платформа
bpl: Платформа
bpl_id: Платформа
update_type: Критичность обновления update_type: Критичность обновления
build_requires: Пересборка с зависимостями build_requires: Пересборка с зависимостями
auto_publish: Автоматическая публикация auto_publish: Автоматическая публикация
@ -37,6 +35,12 @@ ru:
version: Версия version: Версия
build_list: Сборочный лист build_list: Сборочный лист
build_list/package:
name: Название
fullname: Полное имя
release: Релиз
version: Версия
layout: layout:
build_lists: build_lists:
filter_header: Фильтр filter_header: Фильтр
@ -49,6 +53,7 @@ ru:
project_name_search: Поиск по названию проекта project_name_search: Поиск по названию проекта
bs_id_not_set: Id еще не присвоен bs_id_not_set: Id еще не присвоен
items_header: Элементы сборки items_header: Элементы сборки
packages_header: Данные о контейнере
no_items_data: Данных нет no_items_data: Данных нет
show: Просмотр show: Просмотр
cancel_success: 'Сборка отменена.' cancel_success: 'Сборка отменена.'
@ -65,6 +70,9 @@ ru:
human_current_duration: Сборка длится уже %{hours} ч. %{minutes} мин. human_current_duration: Сборка длится уже %{hours} ч. %{minutes} мин.
human_duration: Собрано за %{hours} ч. %{minutes} мин. human_duration: Собрано за %{hours} ч. %{minutes} мин.
attached_advisory: Связанный бюллетень
create_advisory: Создать новый бюллетень
ownership: ownership:
header: Принадлежность заданий header: Принадлежность заданий
owned: Мне owned: Мне
@ -107,8 +115,8 @@ ru:
flash: flash:
build_list: build_list:
saved: Билд лист для версии '%{project_version}', платформы '%{bpl}' и архитектуры '%{arch}' создан успешно saved: Билд лист для версии '%{project_version}', платформы '%{build_for_platform}' и архитектуры '%{arch}' создан успешно
save_error: Не удалось сохранить билд лист для версии '%{project_version}', платформы '%{bpl}' и архитектуры '%{arch}' save_error: Не удалось сохранить билд лист для версии '%{project_version}', платформы '%{build_for_platform}' и архитектуры '%{arch}'
no_project_version_selected: Выберите какую-нибудь версию no_project_version_selected: Выберите какую-нибудь версию
no_project_version_found: Выбранная версия '%{project_version}' не найдена no_project_version_found: Выбранная версия '%{project_version}' не найдена
no_arch_or_platform_selected: Выберите хотя бы одну архитектуру и платформу no_arch_or_platform_selected: Выберите хотя бы одну архитектуру и платформу

View File

@ -88,3 +88,6 @@ en:
group: Group group: Group
default_branch: Default branch default_branch: Default branch
is_rpm: Project is a packet 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 (_)

View File

@ -88,3 +88,6 @@ ru:
group: Группа group: Группа
default_branch: Ветка по умолчанию default_branch: Ветка по умолчанию
is_rpm: Проект является пакетом is_rpm: Проект является пакетом
errors:
project:
uname: В имени можно использовать только строчные символы латинского алфавита (a-z), цифры (0-9) и символ нижнего подчеркивания (_)

View File

@ -3,14 +3,13 @@ en:
'Editing' 'Editing'
at: at at: at
users: users:
settings:
profile: profile:
title: 'Your Profile' title: 'Your Profile'
projects:
build_lists: build_lists:
index: index:
title: 'Projects Monitoring' title: 'Projects Monitoring'
product_build_lists:
index:
title: 'Products Monitoring'
git: git:
commits: commits:
index: index:
@ -23,6 +22,10 @@ en:
title: 'Compare Revisions' title: 'Compare Revisions'
searching: searching:
title: 'Search in Wiki' title: 'Search in Wiki'
platforms:
product_build_lists:
index:
title: 'Products Monitoring'
pull_requests: pull_requests:
index: index:
title: 'Pull Requests' title: 'Pull Requests'

View File

@ -3,14 +3,13 @@ ru:
'Редактирование' 'Редактирование'
at: at at: at
users: users:
settings:
profile: profile:
title: 'Ваш профиль' title: 'Ваш профиль'
projects:
build_lists: build_lists:
index: index:
title: 'Мониторинг проектов' title: 'Мониторинг проектов'
product_build_lists:
index:
title: 'Мониторинг продуктов'
git: git:
commits: commits:
index: index:
@ -23,6 +22,10 @@ ru:
title: 'Сравнение версий' title: 'Сравнение версий'
searching: searching:
title: 'Поиск в вики' title: 'Поиск в вики'
platforms:
product_build_lists:
index:
title: 'Мониторинг продуктов'
pull_requests: pull_requests:
index: index:
title: 'Запросы на слияние' title: 'Запросы на слияние'

View File

@ -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!
<br/><br/>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.

View File

@ -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-репозиторий, который можно клонировать, использовать в режиме офлайн, изменять и загружать изменения обратно на
сервер, как в случае с обычным кодом. Удобный веб-редактор позволит работать с ней в онлайн. Теперь данные о проекте не
пропадут и доступны для редактирования в любимом редакторе!
<br/><br/>Примечание: для приватного проекта вики доступна только его участникам. Для публичного — всем для чтения.
tracker: |
Каждый проект также может использовать легкий и простой трекер задач. Метки и назначения позволят не потеряться среди
задач, а понятный интерфейс позволит сконцентрироваться на работе, а не на заполнении огромных формуляров.

View File

@ -9,6 +9,7 @@ Rosa::Application.routes.draw do
get '/forbidden' => 'pages#forbidden', :as => 'forbidden' get '/forbidden' => 'pages#forbidden', :as => 'forbidden'
get '/terms-of-service' => 'pages#tos', :as => 'tos' 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/ get '/activity_feeds.:format' => 'activity_feeds#index', :as => 'atom_activity_feeds', :format => /atom/
if APP_CONFIG['anonymous_access'] if APP_CONFIG['anonymous_access']
@ -20,6 +21,22 @@ Rosa::Application.routes.draw do
root :to => 'activity_feeds#index' root :to => 'activity_feeds#index'
end 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 scope :module => 'platforms' do
resources :platforms do resources :platforms do
resources :private_users, :except => [:show, :destroy, :update] resources :private_users, :except => [:show, :destroy, :update]
@ -49,20 +66,6 @@ Rosa::Application.routes.draw do
resources :product_build_lists, :only => [:index] resources :product_build_lists, :only => [:index]
end 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 scope :module => 'users' do
resources :settings, :only => [] do resources :settings, :only => [] do
collection do collection do
@ -82,6 +85,8 @@ Rosa::Application.routes.draw do
end end
scope :module => 'groups' do 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 resources :groups, :controller => 'profile' do
get :autocomplete_group_uname, :on => :collection get :autocomplete_group_uname, :on => :collection
delete :remove_user, :on => :member delete :remove_user, :on => :member
@ -105,25 +110,17 @@ Rosa::Application.routes.draw do
match 'build_lists/new_bbdt', :to => "build_lists#new_bbdt" match 'build_lists/new_bbdt', :to => "build_lists#new_bbdt"
match 'product_status', :to => 'product_build_lists#status_build' 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 member do
put :cancel put :cancel
put :publish
put :reject_publish
end end
collection { post :search } collection { post :search }
end end
resources :projects, :only => [:index, :new, :create] resources :projects, :only => [:index, :new, :create]
end
scope ':owner_name' do # Owner scope ':owner_name/:project_name', :constraints => {:project_name => Project::NAME_REGEXP} do # project
constraints OwnerConstraint.new(User) do scope :as => 'project' 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 resources :wiki do
collection do collection do
match '_history' => 'wiki#wiki_history', :as => :history, :via => :get match '_history' => 'wiki#wiki_history', :as => :history, :via => :get
@ -175,9 +172,8 @@ Rosa::Application.routes.draw do
put :merge, :as => 'merge' put :merge, :as => 'merge'
end end
end end
end end
scope ':project_name', :module => 'projects' do
# Resource # Resource
get '/edit' => 'projects#edit', :as => :edit_project get '/edit' => 'projects#edit', :as => :edit_project
put '/' => 'projects#update' 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/ get '/archive/:format/tree/:treeish' => "git/trees#archive", :defaults => {:treeish => :master}, :as => :archive, :format => /zip|tar/
end end
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 end

View File

@ -10,3 +10,7 @@
every 1.day, :at => '4:00 am' do every 1.day, :at => '4:00 am' do
rake "import:sync:all", :output => 'log/sync.log' rake "import:sync:all", :output => 'log/sync.log'
end end
every 1.day, :at => '3:50 am' do
rake "buildlist:clear:outdated", :output => 'log/build_list_clear.log'
end

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -11,7 +11,7 @@
# #
# It's strongly recommended to check this file into your version control system. # 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| create_table "activity_feeds", :force => true do |t|
t.integer "user_id", :null => false t.integer "user_id", :null => false
@ -21,6 +21,29 @@ ActiveRecord::Schema.define(:version => 20120425190938) do
t.datetime "updated_at", :null => false t.datetime "updated_at", :null => false
end 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| create_table "arches", :force => true do |t|
t.string "name", :null => false t.string "name", :null => false
t.datetime "created_at", :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" 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| create_table "build_lists", :force => true do |t|
t.integer "bs_id" t.integer "bs_id"
t.string "container_path" t.string "container_path"
@ -67,8 +107,8 @@ ActiveRecord::Schema.define(:version => 20120425190938) do
t.string "name" t.string "name"
t.boolean "build_requires", :default => false t.boolean "build_requires", :default => false
t.string "update_type" t.string "update_type"
t.integer "bpl_id" t.integer "build_for_platform_id"
t.integer "pl_id" t.integer "save_to_platform_id"
t.text "include_repos" t.text "include_repos"
t.integer "user_id" t.integer "user_id"
t.boolean "auto_publish", :default => true t.boolean "auto_publish", :default => true
@ -77,8 +117,10 @@ ActiveRecord::Schema.define(:version => 20120425190938) do
t.integer "priority", :default => 0, :null => false t.integer "priority", :default => 0, :null => false
t.datetime "started_at" t.datetime "started_at"
t.integer "duration" t.integer "duration"
t.integer "advisory_id"
end 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", ["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", ["bs_id"], :name => "index_build_lists_on_bs_id", :unique => true
add_index "build_lists", ["project_id"], :name => "index_build_lists_on_project_id" add_index "build_lists", ["project_id"], :name => "index_build_lists_on_project_id"
@ -332,7 +374,7 @@ ActiveRecord::Schema.define(:version => 20120425190938) do
create_table "users", :force => true do |t| create_table "users", :force => true do |t|
t.string "name" t.string "name"
t.string "email", :default => "", :null => false t.string "email", :default => "", :null => false
t.string "encrypted_password", :limit => 128, :default => "", :null => false t.string "encrypted_password", :default => "", :null => false
t.string "reset_password_token" t.string "reset_password_token"
t.datetime "reset_password_sent_at" t.datetime "reset_password_sent_at"
t.datetime "remember_created_at" t.datetime "remember_created_at"
@ -342,8 +384,10 @@ ActiveRecord::Schema.define(:version => 20120425190938) do
t.string "uname" t.string "uname"
t.string "role" t.string "role"
t.string "language", :default => "en" t.string "language", :default => "en"
t.datetime "reset_password_sent_at"
t.integer "own_projects_count", :default => 0, :null => false 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.text "professional_experience"
t.string "site" t.string "site"
t.string "company" t.string "company"
@ -356,6 +400,7 @@ ActiveRecord::Schema.define(:version => 20120425190938) do
t.string "unlock_token" t.string "unlock_token"
t.datetime "locked_at" t.datetime "locked_at"
t.string "authentication_token" t.string "authentication_token"
t.integer "build_priority", :default => 50
end end
add_index "users", ["authentication_token"], :name => "index_users_on_authentication_token" add_index "users", ["authentication_token"], :name => "index_users_on_authentication_token"

View File

@ -7,6 +7,6 @@ class OwnerConstraint
end end
def matches?(request) def matches?(request)
@class_name.send(@finder, request.params[:owner_name]).present? @class_name.send(@finder, request.params[:uname]).present?
end end
end end

View File

@ -23,6 +23,7 @@ class ReservedNameValidator < ActiveModel::EachValidator
unfollow unsubscribe url user unfollow unsubscribe url user
widget widgets wiki widget widgets wiki
xfn xmpp xfn xmpp
tour
} }
def reserved_names def reserved_names

16
lib/tasks/buildlist.rake Normal file
View File

@ -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

View File

@ -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

View File

@ -3,7 +3,7 @@ require 'spec_helper'
describe Groups::MembersController do describe Groups::MembersController do
before(:each) do before(:each) do
stub_rsync_methods stub_symlink_methods
@group = FactoryGirl.create(:group) @group = FactoryGirl.create(:group)
@user = @group.owner @user = @group.owner
set_session_for @user set_session_for @user

View File

@ -69,7 +69,7 @@ end
describe Groups::ProfileController do describe Groups::ProfileController do
before(:each) do before(:each) do
stub_rsync_methods stub_symlink_methods
@group = FactoryGirl.create(:group) @group = FactoryGirl.create(:group)
@another_user = FactoryGirl.create(:user) @another_user = FactoryGirl.create(:user)
@create_params = {:group => {:description => 'grp1', :uname => 'un_grp1'}} @create_params = {:group => {:description => 'grp1', :uname => 'un_grp1'}}

Some files were not shown because too many files have changed in this diff Show More