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'
# deploy
gem 'capistrano', :require => false
gem 'rvm-capistrano', :require => false
gem 'cape', :require => false
gem 'capistrano_colors', :require => false
end

View File

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

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() {
$('#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 ) {

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

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

View File

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

View File

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

View File

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

View File

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

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

View File

@ -5,7 +5,7 @@ module PlatformsHelper
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

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 => '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

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
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,6 +88,7 @@ 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
@ -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

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

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

View File

@ -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_\-]+$/ }
@ -24,8 +28,9 @@ class Platform < ActiveRecord::Base
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")
@ -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
@ -119,10 +124,10 @@ class Platform < ActiveRecord::Base
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

View File

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

View File

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

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')]
= 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')

View File

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

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
- act = action_name.to_sym; contr = controller_name.to_sym
.left= platfrom_printed_name(@platform)
.left= platform_printed_name(@platform)
%nav
%ul

View File

@ -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= link_to platform_printed_name(platform), platform_path(platform)
%td= platform.distrib_type

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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: Выберите хотя бы одну архитектуру и платформу

View File

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

View File

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

View File

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

View File

@ -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: 'Запросы на слияние'

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 '/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

View File

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

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.
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"

View File

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

View File

@ -23,6 +23,7 @@ class ReservedNameValidator < ActiveModel::EachValidator
unfollow unsubscribe url user
widget widgets wiki
xfn xmpp
tour
}
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
before(:each) do
stub_rsync_methods
stub_symlink_methods
@group = FactoryGirl.create(:group)
@user = @group.owner
set_session_for @user

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