Merge branch 'master' into 263-refactoring
Conflicts: config/deploy.rb db/schema.rb
This commit is contained in:
commit
2c1df5cd14
Binary file not shown.
After Width: | Height: | Size: 450 B |
|
@ -0,0 +1,23 @@
|
|||
Rosa.Views.ProjectModifyView = Backbone.View.extend({
|
||||
initialize: function() {
|
||||
_.bindAll(this, 'checkboxClick');
|
||||
|
||||
this.$checkbox_wrapper = $('#niceCheckbox1');
|
||||
this._$checkbox = this.$checkbox_wrapper.children('#project_is_package').first();
|
||||
this.$maintainer_form = $('#maintainer_form');
|
||||
|
||||
this.$checkbox_wrapper.on('click', this.checkboxClick);
|
||||
},
|
||||
|
||||
checkboxClick: function() {
|
||||
if (this._$checkbox.is(':checked')) {
|
||||
this.$maintainer_form.slideDown();
|
||||
} else {
|
||||
this.$maintainer_form.slideUp();
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.checkboxClick();
|
||||
}
|
||||
});
|
|
@ -1,32 +1,32 @@
|
|||
function changeCheck(el) {
|
||||
var el = el, input = el.find('input[type="checkbox"]');
|
||||
|
||||
if(input.attr("checked")) {
|
||||
el.css('backgroundPosition', '0 0');
|
||||
input.removeAttr('checked');
|
||||
} else {
|
||||
el.css('backgroundPosition', '0 -18px');
|
||||
input.attr('checked', true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function startChangeCheck(el) {
|
||||
var el = el, input = el.find('input[type="checkbox"]');
|
||||
|
||||
if(input.attr('checked')) {
|
||||
el.css('backgroundPosition', '0 -18px');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
$('.niceCheck-main').each(function(i,el) {
|
||||
startChangeCheck($(el));
|
||||
});
|
||||
$('.niceCheck-main').click(function() {
|
||||
changeCheck($(this));
|
||||
});
|
||||
});
|
||||
function changeCheck(el) {
|
||||
var input = el.find('input[type="checkbox"]');
|
||||
|
||||
if(input.attr("checked")) {
|
||||
el.css('backgroundPosition', '0 0');
|
||||
input.removeAttr('checked');
|
||||
} else {
|
||||
el.css('backgroundPosition', '0 -18px');
|
||||
input.attr('checked', true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function startChangeCheck(el) {
|
||||
var input = el.find('input[type="checkbox"]');
|
||||
|
||||
if(input.attr('checked')) {
|
||||
el.css('backgroundPosition', '0 -18px');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
$('.niceCheck-main').each(function(i,el) {
|
||||
startChangeCheck($(el));
|
||||
});
|
||||
$('.niceCheck-main').click(function() {
|
||||
changeCheck($(this));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@ $(document).ready(function() {
|
|||
var base_platforms = $('.all_platforms input[type=checkbox].build_bpl_ids');
|
||||
|
||||
base_platforms.each(function(){
|
||||
if ($.inArray(platform_id, base_platforms.map(function(){ return $(this).val() }).get()) >= 0) {
|
||||
if ($.inArray(platform_id, base_platforms.map(function(){ return $(this).val(); }).get()) >= 0) {
|
||||
if ($(this).val() == platform_id) {
|
||||
if ($(this).attr('data-released') === '1') {
|
||||
$('#build_list_auto_publish').removeAttr('checked').attr('disabled', 'disabled');
|
||||
|
@ -34,7 +34,7 @@ $(document).ready(function() {
|
|||
}
|
||||
});
|
||||
|
||||
if ($.inArray(platform_id, base_platforms.map(function(){ return $(this).val() }).get()) == -1) {
|
||||
if ($.inArray(platform_id, base_platforms.map(function(){ return $(this).val(); }).get()) === -1) {
|
||||
// For personal platforms update types always enebaled:
|
||||
enableUpdateTypes();
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ function setPlChecked(pointer, checked) {
|
|||
var pl_id = pl_cbx.val();
|
||||
if (checked && !$(pointer).attr('disabled')) {
|
||||
pl_cbx.attr('checked', 'checked').trigger('change');
|
||||
} else if ($('input[pl_id=' + pl_id + '][checked="checked"]').size() == 0) {
|
||||
} else if ($('input[pl_id=' + pl_id + '][checked="checked"]').size() === 0) {
|
||||
pl_cbx.removeAttr('checked').trigger('change');
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,10 @@ function setBranchSelected() {
|
|||
if ( branch_pl_opt.size() > 0 ) {
|
||||
$('#build_list_project_version option[selected]').removeAttr('selected');
|
||||
branch_pl_opt.attr('selected', 'selected');
|
||||
var bl_version_sel = $('#build_list_project_version');
|
||||
bl_version_sel.val(branch_pl_opt);
|
||||
// hack for FF to force render of select box.
|
||||
bl_version_sel[0].innerHTML = bl_version_sel[0].innerHTML;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ $(document).ready(function() {
|
|||
form.fadeOut('slow');
|
||||
$('#edit_issue_content').fadeIn('slow');
|
||||
$('h3.issue_title').html(form.find('#issue_title').attr('value'));
|
||||
$('.fulltext.view.issue_body').html(form.find('#issue_body').attr('value'));
|
||||
$('.fulltext.view.issue_body').html(data);
|
||||
},
|
||||
error: function(data){
|
||||
alert('error'); // TODO remove
|
||||
|
|
|
@ -1152,19 +1152,19 @@ form.mass_build section.right {
|
|||
}
|
||||
|
||||
/* remove this lines after change to backbone */
|
||||
table.tablesorter.advisories thead tr.search th {
|
||||
table.tablesorter.static-search thead tr.search th {
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
table.tablesorter.advisories thead tr.search th input[type='text'] {
|
||||
table.tablesorter.static-search thead tr.search th input[type='text'] {
|
||||
width: 640px;
|
||||
}
|
||||
|
||||
table.tablesorter.advisories thead tr.search th form {
|
||||
table.tablesorter.static-search thead tr.search th form {
|
||||
float: left;
|
||||
}
|
||||
|
||||
table.tablesorter.advisories thead tr.search th form.button_to {
|
||||
table.tablesorter.static-search thead tr.search th form.button_to {
|
||||
padding: 3px 0 0 7px;
|
||||
}
|
||||
|
||||
|
@ -1385,10 +1385,103 @@ hr.bootstrap {
|
|||
}
|
||||
}
|
||||
|
||||
time.js-relative-date {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div.reloader {
|
||||
float: right;
|
||||
}
|
||||
|
||||
div.log-wrapper {
|
||||
width: 565px;
|
||||
|
||||
div.log-header {
|
||||
margin-bottom: 10px;
|
||||
|
||||
div.text-wrap, span {
|
||||
height: 16px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
div.text-wrap {
|
||||
width: 545px;
|
||||
float: left;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
background: image-url("trigger.gif") no-repeat scroll left bottom transparent;
|
||||
margin: 1px;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
font-size: 0;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
float: right;
|
||||
}
|
||||
span.closed {
|
||||
background-position: left top;
|
||||
}
|
||||
}
|
||||
|
||||
div.log-body {
|
||||
|
||||
div.reloader, .log {
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.reloader {
|
||||
padding: 5px 10px;
|
||||
border-bottom: none;
|
||||
border-radius: 5px 5px 0 0;
|
||||
|
||||
table.options {
|
||||
border-spacing: 5px 0;
|
||||
|
||||
tr {
|
||||
|
||||
td a {
|
||||
display: inline-block;
|
||||
height: 13px;
|
||||
padding-left: 16px;
|
||||
background: image-url('code.png') no-repeat;
|
||||
padding-bottom: 2px;
|
||||
margin: 2px 0 0 1px;
|
||||
}
|
||||
td.first {
|
||||
padding-right: 5px;
|
||||
}
|
||||
td.last {
|
||||
border-left: 1px solid #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
tr.bottom {
|
||||
td {
|
||||
padding-left: 5px;
|
||||
}
|
||||
td.first {
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.log {
|
||||
background: #f8f8f8;
|
||||
height: 500px;
|
||||
width: 543px;
|
||||
min-width: 543px;
|
||||
border-radius: 5px 0 5px 5px;
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
margin: 0;
|
||||
font-family: monospace;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table.tablesorter.platform-maintainers.static-search thead tr.search th input[type="text"] {
|
||||
width: 430px;
|
||||
}
|
||||
|
|
|
@ -9,11 +9,11 @@ class PagesController < ApplicationController
|
|||
|
||||
def tour_inside
|
||||
@entries = case params[:id]
|
||||
when 'projects'
|
||||
when 'builds'
|
||||
%w(repo builds monitoring)
|
||||
when 'sources'
|
||||
%w(source history annotation edit)
|
||||
when 'builds'
|
||||
when 'projects'
|
||||
%w(control git tracker)
|
||||
end
|
||||
render "pages/tour/tour-inside", :layout => 'tour'
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# -*- encoding : utf-8 -*-
|
||||
class Platforms::MaintainersController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
skip_before_filter :authenticate_user!, :only => [:index] if APP_CONFIG['anonymous_access']
|
||||
load_and_authorize_resource :platform
|
||||
|
||||
def index
|
||||
@maintainers = BuildList::Package.actual.by_platform(@platform)
|
||||
.order('lower(name) ASC, length(name) ASC')
|
||||
.includes(:project)
|
||||
@maintainers = @maintainers.where('name ILIKE ?', "%#{params[:q]}%") if params[:q].present?
|
||||
@maintainers = @maintainers.paginate(:page => params[:page])
|
||||
end
|
||||
|
||||
end
|
|
@ -5,9 +5,9 @@ class Projects::BuildListsController < Projects::BaseController
|
|||
|
||||
before_filter :authenticate_user!, :except => CALLBACK_ACTIONS
|
||||
before_filter :authenticate_build_service!, :only => CALLBACK_ACTIONS
|
||||
skip_before_filter :authenticate_user!, :only => [:show, :index, :search] if APP_CONFIG['anonymous_access']
|
||||
skip_before_filter :authenticate_user!, :only => [:show, :index, :search, :log] if APP_CONFIG['anonymous_access']
|
||||
|
||||
before_filter :find_build_list, :only => [:show, :publish, :cancel, :update]
|
||||
before_filter :find_build_list, :only => [:show, :publish, :cancel, :update, :log]
|
||||
before_filter :find_build_list_by_bs, :only => [:publish_build, :status_build, :pre_build, :post_build, :circle_build]
|
||||
|
||||
load_and_authorize_resource :project, :only => NESTED_ACTIONS
|
||||
|
@ -101,6 +101,15 @@ class Projects::BuildListsController < Projects::BaseController
|
|||
end
|
||||
end
|
||||
|
||||
def log
|
||||
@log = `tail -n #{params[:load_lines].to_i} #{Rails.root + 'public' + @build_list.fs_log_path}`
|
||||
@log = t("layout.build_lists.log.not_available") unless $?.success?
|
||||
|
||||
respond_to do |format|
|
||||
format.json { render :json => { :log => @log, :building => @build_list.build_started? } }
|
||||
end
|
||||
end
|
||||
|
||||
def publish_build
|
||||
if params[:status].to_i == 0 # ok
|
||||
@build_list.published
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
# -*- encoding : utf-8 -*-
|
||||
class Projects::IssuesController < Projects::BaseController
|
||||
NON_RESTFUL_ACTION = [:create_label, :update_label, :destroy_label, :search_collaborators]
|
||||
NON_RESTFUL_ACTION = [:create_label, :update_label, :destroy_label]
|
||||
before_filter :authenticate_user!
|
||||
skip_before_filter :authenticate_user!, :only => [:index, :show] if APP_CONFIG['anonymous_access']
|
||||
load_resource :project
|
||||
load_and_authorize_resource :issue, :through => :project, :find_by => :serial_id, :only => [:show, :edit, :update, :destroy, :new, :create, :index]
|
||||
before_filter :load_and_authorize_label, :only => NON_RESTFUL_ACTION
|
||||
|
||||
layout 'application'
|
||||
layout false, :only => [:update, :search_collaborators]
|
||||
|
||||
def index(status = 200)
|
||||
@is_assigned_to_me = params[:filter] == 'to_me'
|
||||
|
@ -16,35 +16,28 @@ class Projects::IssuesController < Projects::BaseController
|
|||
@issues = @project.issues
|
||||
@issues = @issues.where(:assignee_id => current_user.id) if @is_assigned_to_me
|
||||
@issues = @issues.joins(:labels).where(:labels => {:name => @labels}) unless @labels == []
|
||||
# Using mb_chars for correct transform to lowercase ('Русский Текст'.downcase => "Русский Текст")
|
||||
@issues = @issues.where('issues.title ILIKE ?', "%#{params[:search_issue].mb_chars.downcase}%") if params[:search_issue]
|
||||
|
||||
if params[:search_issue]
|
||||
@issues = @issues.where('issues.title ILIKE ?', "%#{params[:search_issue].mb_chars.downcase}%")
|
||||
end
|
||||
@opened_issues = @issues.opened.count
|
||||
@closed_issues = @issues.closed.count
|
||||
@opened_issues, @closed_issues = @issues.opened.count, @issues.closed.count
|
||||
@issues = @issues.where(:status => @status)
|
||||
|
||||
|
||||
@issues = @issues.includes(:assignee, :user).order('serial_id desc').uniq.paginate :per_page => 10, :page => params[:page]
|
||||
.includes(:assignee, :user).order('serial_id desc').uniq.paginate :per_page => 10, :page => params[:page]
|
||||
if status == 200
|
||||
render 'index', :layout => request.format == '*/*' ? 'issues' : 'application' # maybe FIXME '*/*'?
|
||||
render 'index', :layout => request.xhr? ? 'issues' : 'application'
|
||||
else
|
||||
render :status => status, :nothing => true
|
||||
end
|
||||
end
|
||||
|
||||
def new
|
||||
@issue = @project.issues.new
|
||||
end
|
||||
|
||||
def create
|
||||
@assignee_uname = params[:assignee_uname]
|
||||
@issue = @project.issues.new(params[:issue])
|
||||
@issue.user_id = current_user.id
|
||||
|
||||
if @issue.save
|
||||
@issue.subscribe_creator(current_user.id)
|
||||
|
||||
flash[:notice] = I18n.t("flash.issue.saved")
|
||||
redirect_to project_issues_path(@project)
|
||||
else
|
||||
|
@ -54,41 +47,35 @@ class Projects::IssuesController < Projects::BaseController
|
|||
end
|
||||
|
||||
def update
|
||||
@issue.labelings.destroy_all if params[:update_labels]
|
||||
if params[:issue] && status = params[:issue][:status]
|
||||
action = 'status'
|
||||
@issue.set_close(current_user) if status == 'closed'
|
||||
@issue.set_open if status == 'open'
|
||||
status = 200 if @issue.save
|
||||
render :partial => action, :status => (status || 500), :layout => false
|
||||
render :partial => 'status', :status => (@issue.save ? 200 : 500)
|
||||
elsif params[:issue]
|
||||
@issue.labelings.destroy_all if params[:issue][:labelings_attributes] # FIXME
|
||||
status = 200 if @issue.update_attributes(params[:issue])
|
||||
render :nothing => true, :status => (status || 500), :layout => false
|
||||
status = @issue.update_attributes(params[:issue]) ? 200 : 500
|
||||
render :inline => ActionController::Base.helpers.simple_format(params[:issue][:body]), :status => status
|
||||
else
|
||||
render :nothing => true, :status => 200, :layout => false
|
||||
render :nothing => true, :status => 200
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@issue.destroy
|
||||
|
||||
flash[:notice] = t("flash.issue.destroyed")
|
||||
redirect_to root_path
|
||||
end
|
||||
|
||||
def create_label
|
||||
status = @project.labels.create!(:name => params[:name], :color => params[:color]) ? 200 : 500
|
||||
index(status)
|
||||
index(@project.labels.create!(:name => params[:name], :color => params[:color]) ? 200 : 500)
|
||||
end
|
||||
|
||||
def update_label
|
||||
status = @label.update_attributes(:name => params[:name], :color => params[:color]) ? 200 : 500
|
||||
index(status)
|
||||
index(@label.update_attributes(:name => params[:name], :color => params[:color]) ? 200 : 500)
|
||||
end
|
||||
|
||||
def destroy_label
|
||||
status = (@label && @label_destroy) ? 200 : 500
|
||||
index(status)
|
||||
index((@label && @label_destroy) ? 200 : 500)
|
||||
end
|
||||
|
||||
def search_collaborators
|
||||
|
@ -96,7 +83,7 @@ class Projects::IssuesController < Projects::BaseController
|
|||
users = User.joins(:groups => :projects).where(:projects => {:id => @project.id}).where("users.uname ILIKE ?", search)
|
||||
users2 = @project.collaborators.where("users.uname ILIKE ?", search)
|
||||
@users = (users + users2).uniq.sort {|x,y| x.uname <=> y.uname}.first(10)
|
||||
render :partial => 'search_collaborators', :layout => false
|
||||
render :partial => 'search_collaborators'
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -37,6 +37,7 @@ class Projects::ProjectsController < Projects::BaseController
|
|||
end
|
||||
|
||||
def update
|
||||
params[:project].delete(:maintainer_id) if params[:project][:maintainer_id].blank?
|
||||
if @project.update_attributes(params[:project])
|
||||
flash[:notice] = t('flash.project.saved')
|
||||
redirect_to @project
|
||||
|
@ -84,6 +85,14 @@ class Projects::ProjectsController < Projects::BaseController
|
|||
redirect_to projects_path
|
||||
end
|
||||
|
||||
def autocomplete_maintainers
|
||||
term, limit = params[:term], params[:limit] || 10
|
||||
items = User.member_of_project(@project)
|
||||
.where("users.name ILIKE ? OR users.uname ILIKE ?", "%#{term}%", "%#{term}%")
|
||||
.limit(limit).map { |u| {:value => u.fullname, :label => u.fullname, :id => u.id} }
|
||||
render :json => items
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def prepare_list(projects)
|
||||
|
|
|
@ -43,4 +43,22 @@ module BuildListsHelper
|
|||
build_list.project_version
|
||||
end
|
||||
end
|
||||
|
||||
def container_url
|
||||
"http://#{request.host_with_port}/downloads#{@build_list.container_path}".html_safe
|
||||
end
|
||||
|
||||
def build_list_log_url(log_type)
|
||||
"http://#{request.host_with_port}/#{@build_list.fs_log_path(log_type)}".html_safe
|
||||
end
|
||||
|
||||
def log_reload_time_options
|
||||
t = I18n.t("layout.build_lists.log.reload_times").map { |i| i.reverse }
|
||||
|
||||
options_for_select(t, t.first).html_safe
|
||||
end
|
||||
|
||||
def log_reload_lines_options
|
||||
options_for_select([100, 200, 500, 1000, 1500, 2000], 1000).html_safe
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,7 +17,7 @@ class Ability
|
|||
can :archive, Project, :visibility => 'open'
|
||||
can :read, Issue, :project => {:visibility => 'open'}
|
||||
can :search, BuildList
|
||||
can [:read, :everything], BuildList, :project => {:visibility => 'open'}
|
||||
can [:read, :log, :everything], BuildList, :project => {:visibility => 'open'}
|
||||
can :read, ProductBuildList#, :product => {:platform => {:visibility => 'open'}} # double nested hash don't work
|
||||
can :read, Advisory
|
||||
can(:advisories, Platform) {APP_CONFIG['anonymous_access']}
|
||||
|
@ -62,10 +62,10 @@ class Ability
|
|||
can(:destroy, Project) {|project| project.owner_type == 'Group' and project.owner.actors.exists?(:actor_type => 'User', :actor_id => user.id, :role => 'admin')}
|
||||
can :remove_user, Project
|
||||
|
||||
can [:read, :owned, :everything], BuildList, :user_id => user.id
|
||||
can [:read, :related, :everything], BuildList, :project => {:owner_type => 'User', :owner_id => user.id}
|
||||
can [:read, :related, :everything], BuildList, :project => {:owner_type => 'Group', :owner_id => user.group_ids}
|
||||
can([:read, :everything], BuildList, read_relations_for('build_lists', 'projects')) {|build_list| can? :read, build_list.project}
|
||||
can [:read, :log, :owned, :everything], BuildList, :user_id => user.id
|
||||
can [:read, :log, :related, :everything], BuildList, :project => {:owner_type => 'User', :owner_id => user.id}
|
||||
can [:read, :log, :related, :everything], BuildList, :project => {:owner_type => 'Group', :owner_id => user.group_ids}
|
||||
can([:read, :log, :everything], BuildList, read_relations_for('build_lists', 'projects')) {|build_list| can? :read, build_list.project}
|
||||
can([:create, :update], BuildList) {|build_list| build_list.project.is_package && can?(:write, build_list.project)}
|
||||
|
||||
can(:publish, BuildList) do |build_list|
|
||||
|
@ -114,7 +114,7 @@ class Ability
|
|||
can :read, Issue, :project => {:owner_type => 'User', :owner_id => user.id}
|
||||
can :read, Issue, :project => {:owner_type => 'Group', :owner_id => user.group_ids}
|
||||
can(:read, Issue, read_relations_for('issues', 'projects')) {|issue| can? :read, issue.project rescue nil}
|
||||
can(:create, Issue) {|issue| can? :write, issue.project}
|
||||
can(:create, Issue) {|issue| can? :read, issue.project}
|
||||
can([:update, :destroy], Issue) {|issue| issue.user_id == user.id or local_admin?(issue.project)}
|
||||
cannot :manage, Issue, :project => {:has_issues => false} # switch off issues
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ class ActivityFeedObserver < ActiveRecord::Observer
|
|||
else
|
||||
kind = 'git_new_push_notification'
|
||||
options = {:project_id => record.project.id, :project_name => record.project.name, :last_commits => last_commits, :branch_name => branch_name,
|
||||
:change_type => change_type, :user_email => record.project.repo.repo.log(branch_name, nil).first.author.email,
|
||||
:change_type => change_type, :user_email => record.project.repo.log(branch_name, nil).first.author.email,
|
||||
:project_owner => record.project.owner.uname}
|
||||
options.merge!({:user_id => first_commiter.id, :user_name => first_commiter.name}) if first_commiter
|
||||
end
|
||||
|
|
|
@ -79,7 +79,7 @@ class BuildList < ActiveRecord::Base
|
|||
scope :recent, order("#{table_name}.updated_at DESC")
|
||||
scope :for_status, lambda {|status| where(:status => status) }
|
||||
scope :for_user, lambda { |user| where(:user_id => user.id) }
|
||||
scope :for_platform, lambda { |platform| where(:build_for_platform_id => platform.id) }
|
||||
scope :for_platform, lambda { |platform| where(:build_for_platform_id => platform) }
|
||||
scope :by_mass_build, lambda { |mass_build| where(:mass_build_id => mass_build) }
|
||||
scope :scoped_to_arch, lambda {|arch| where(:arch_id => arch) }
|
||||
scope :scoped_to_save_platform, lambda {|pl_id| where(:save_to_platform_id => pl_id) }
|
||||
|
@ -125,7 +125,7 @@ class BuildList < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
after_transition :on => :published, :do => :set_version_and_tag
|
||||
after_transition :on => :published, :do => [:set_version_and_tag, :actualize_packages]
|
||||
|
||||
event :place_build do
|
||||
transition :waiting_for_response => :build_pending, :if => lambda { |build_list|
|
||||
|
@ -201,6 +201,19 @@ class BuildList < ActiveRecord::Base
|
|||
save
|
||||
end
|
||||
|
||||
def actualize_packages
|
||||
ActiveRecord::Base.transaction do
|
||||
old_pkgs = self.class.where(:project_id => self.project_id)
|
||||
.where(:save_to_repository_id => self.save_to_repository_id)
|
||||
.for_platform(self.build_for_platform_id)
|
||||
.scoped_to_arch(self.arch_id)
|
||||
.for_status(BUILD_PUBLISHED)
|
||||
.recent.limit(2).last.packages # packages from previous build_list
|
||||
old_pkgs.update_all(:actual => false)
|
||||
self.packages.update_all(:actual => true)
|
||||
end
|
||||
end
|
||||
|
||||
#TODO: Share this checking on product owner.
|
||||
def can_cancel?
|
||||
[BUILD_PENDING, BuildServer::PLATFORM_PENDING].include?(status) && bs_id
|
||||
|
@ -266,6 +279,10 @@ class BuildList < ActiveRecord::Base
|
|||
I18n.t("layout.build_lists.human_duration", {:hours => (duration/3600).to_i, :minutes => (duration%3600/60).to_i})
|
||||
end
|
||||
|
||||
def fs_log_path(log_type = :build)
|
||||
container_path? ? "downloads/#{container_path}/log/#{project.name}/#{log_type.to_s}.log" : nil
|
||||
end
|
||||
|
||||
def in_work?
|
||||
status == BuildServer::BUILD_STARTED
|
||||
#[WAITING_FOR_RESPONSE, BuildServer::BUILD_PENDING, BuildServer::BUILD_STARTED].include?(status)
|
||||
|
|
|
@ -7,6 +7,18 @@ class BuildList::Package < ActiveRecord::Base
|
|||
|
||||
attr_accessible :fullname, :name, :release, :version
|
||||
|
||||
validates :build_list_id, :project_id, :platform_id, :fullname, :package_type, :name, :release, :version, :presence => true
|
||||
validates :build_list_id, :project_id, :platform_id, :fullname,
|
||||
:package_type, :name, :release, :version,
|
||||
:presence => true
|
||||
validates :package_type, :inclusion => PACKAGE_TYPES
|
||||
|
||||
# Fetches only actual (last publised) packages.
|
||||
scope :actual, where(:actual => true)
|
||||
scope :by_platform, lambda {|platform| where(:platform_id => platform) }
|
||||
scope :by_name, lambda {|name| where(:name => name) }
|
||||
scope :by_package_type, lambda {|type| where(:package_type => type) }
|
||||
|
||||
def assignee
|
||||
project.maintainer
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,6 +5,7 @@ class Project < ActiveRecord::Base
|
|||
NAME_REGEXP = /[a-zA-Z0-9_\-\+\.]+/
|
||||
|
||||
belongs_to :owner, :polymorphic => true, :counter_cache => :own_projects_count
|
||||
belongs_to :maintainer, :class_name => "User"
|
||||
|
||||
has_many :issues, :dependent => :destroy
|
||||
has_many :labels, :dependent => :destroy
|
||||
|
@ -21,12 +22,15 @@ class Project < ActiveRecord::Base
|
|||
has_many :packages, :class_name => "BuildList::Package", :dependent => :destroy
|
||||
has_and_belongs_to_many :advisories # should be without :dependent => :destroy
|
||||
|
||||
validates :name, :uniqueness => {:scope => [:owner_id, :owner_type], :case_sensitive => false}, :presence => true, :format => {:with => /^#{NAME_REGEXP}$/, :message => I18n.t("activerecord.errors.project.uname")}
|
||||
validates :name, :uniqueness => {:scope => [:owner_id, :owner_type], :case_sensitive => false},
|
||||
:presence => true,
|
||||
:format => {:with => /^#{NAME_REGEXP}$/, :message => I18n.t("activerecord.errors.project.uname")}
|
||||
validates :owner, :presence => true
|
||||
validates :maintainer_id, :presence => true, :unless => :new_record?
|
||||
validates :visibility, :presence => true, :inclusion => {:in => VISIBILITIES}
|
||||
validate { errors.add(:base, :can_have_less_or_equal, :count => MAX_OWN_PROJECTS) if owner.projects.size >= MAX_OWN_PROJECTS }
|
||||
|
||||
attr_accessible :name, :description, :visibility, :srpm, :is_package, :default_branch, :has_issues, :has_wiki
|
||||
attr_accessible :name, :description, :visibility, :srpm, :is_package, :default_branch, :has_issues, :has_wiki, :maintainer_id
|
||||
attr_readonly :name, :owner_id, :owner_type
|
||||
|
||||
scope :recent, order("name ASC")
|
||||
|
@ -35,8 +39,18 @@ class Project < ActiveRecord::Base
|
|||
scope :by_name, lambda {|name| where('projects.name ILIKE ?', name)}
|
||||
scope :by_visibilities, lambda {|v| where(:visibility => v)}
|
||||
scope :opened, where(:visibility => 'open')
|
||||
scope :addable_to_repository, lambda { |repository_id| where("projects.id NOT IN (SELECT project_to_repositories.project_id FROM project_to_repositories WHERE (project_to_repositories.repository_id = #{ repository_id }))") }
|
||||
scope :package, where(:is_package => true)
|
||||
scope :addable_to_repository, lambda { |repository_id| where %Q(
|
||||
projects.id NOT IN (
|
||||
SELECT
|
||||
ptr.project_id
|
||||
FROM
|
||||
project_to_repositories AS ptr
|
||||
WHERE (ptr.repository_id = #{ repository_id })
|
||||
)
|
||||
) }
|
||||
|
||||
before_create :set_maintainer
|
||||
after_create :attach_to_personal_repository
|
||||
|
||||
has_ancestry :orphan_strategy => :rootify #:adopt not available yet
|
||||
|
@ -120,6 +134,8 @@ class Project < ActiveRecord::Base
|
|||
c.parent_id = id
|
||||
c.owner = new_owner
|
||||
c.updated_at = nil; c.created_at = nil # :id = nil
|
||||
# Hack to call protected method :)
|
||||
c.send :set_maintainer
|
||||
c.save
|
||||
end
|
||||
end
|
||||
|
@ -128,6 +144,10 @@ class Project < ActiveRecord::Base
|
|||
I18n.t("layout.projects.human_average_build_time", {:hours => (average_build_time/3600).to_i, :minutes => (average_build_time%3600/60).to_i})
|
||||
end
|
||||
|
||||
def formatted_average_build_time
|
||||
"%02d:%02d" % [average_build_time / 3600, average_build_time % 3600 / 60]
|
||||
end
|
||||
|
||||
def xml_rpc_create(repository)
|
||||
result = BuildServer.create_project name, repository.platform.name, repository.name, path
|
||||
if result == BuildServer::SUCCESS
|
||||
|
@ -151,4 +171,9 @@ class Project < ActiveRecord::Base
|
|||
def attach_to_personal_repository
|
||||
repositories << self.owner.personal_repository if !repositories.exists?(:id => self.owner.personal_repository)
|
||||
end
|
||||
|
||||
def set_maintainer
|
||||
self.maintainer_id = (owner_type == 'User') ? self.owner_id : self.owner.owner_id
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -52,6 +52,10 @@ class User < ActiveRecord::Base
|
|||
scope :admin, where(:role => 'admin')
|
||||
scope :real, where(:role => ['', nil])
|
||||
|
||||
scope :member_of_project, lambda {|item|
|
||||
where "#{table_name}.id IN (?)", item.members.map(&:id).uniq
|
||||
}
|
||||
|
||||
after_create lambda { self.create_notifier }
|
||||
before_create :ensure_authentication_token
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
class MaintainerPresenter < ApplicationPresenter
|
||||
|
||||
attr_reader :package, :package_link, :package_name, :package_type,
|
||||
:package_version, :package_release, :package_version_release,
|
||||
:package_updated_at
|
||||
attr_reader :maintainer, :maintainer_fullname, :maintainer_email,
|
||||
:maintainer_link, :maintainer_mail_link
|
||||
delegate :package_type, :to => :package
|
||||
|
||||
[:name, :version, :release, :updated_at].each do |meth|
|
||||
define_method "package_#{meth}" do
|
||||
@package.send meth
|
||||
end
|
||||
end
|
||||
|
||||
[:fullname, :email].each do |meth|
|
||||
define_method "maintainer_#{meth}" do
|
||||
@maintainer.send meth
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(package, opts = {})
|
||||
@package = package
|
||||
@maintainer = package.try(:assignee)
|
||||
end
|
||||
|
||||
def package_link
|
||||
link_to @package.name, @package.project
|
||||
end
|
||||
|
||||
def package_version_release
|
||||
"#{@package.version}-#{@package.release}"
|
||||
end
|
||||
|
||||
def maintainer_link
|
||||
link_to @maintainer.fullname, @maintainer
|
||||
end
|
||||
|
||||
def maintainer_email_link
|
||||
mail_to @maintainer.email, @maintainer.email
|
||||
end
|
||||
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
%table#myTable.tablesorter.advisories{:cellspacing => "0", :cellpadding => "0"}
|
||||
%table#myTable.tablesorter.advisories.static-search{:cellspacing => "0", :cellpadding => "0"}
|
||||
%thead
|
||||
%tr
|
||||
%th.th1= t("activerecord.attributes.advisory.advisory_id")
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
.a= link_to t('layout.logout'), destroy_user_session_path, :method => :delete
|
||||
- else
|
||||
.user
|
||||
.profile= link_to t("layout.devise.shared_links.sign_up"), new_register_request_path
|
||||
.profile= link_to t("layout.devise.shared_links.sign_in"), new_user_session_path
|
||||
.right
|
||||
.both
|
||||
|
@ -55,4 +56,4 @@
|
|||
bg_alpha : 0.5,
|
||||
piro_scroll : true //pirobox always positioned at the center of the page
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
= link_to t("layout.platforms.about"), platform_path(@platform)
|
||||
%li{:class => (contr == :repositories) ? 'active' : ''}
|
||||
= link_to t("layout.repositories.list_header"), platform_repositories_path(@platform)
|
||||
- if can? :read, @platform
|
||||
%li{:class => (act == :index && contr == :maintainers) ? 'active' : nil}
|
||||
= link_to t("layout.platforms.maintainers"), platform_maintainers_path(@platform)
|
||||
- if can? :edit, @platform
|
||||
%li{:class => (contr == :mass_builds && [:index, :create].include?(act)) ? 'active' : ''}
|
||||
= link_to t("layout.platforms.mass_build"), platform_mass_builds_path(@platform)
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
%table#myTable.tablesorter.platform-maintainers.static-search{:cellspacing => "0", :cellpadding => "0"}
|
||||
%thead
|
||||
%tr
|
||||
%th.centered= t("activerecord.attributes.maintainer.package_name")
|
||||
%th.centered= t("activerecord.attributes.maintainer.package_type")
|
||||
%th.centered= t("activerecord.attributes.maintainer.version")
|
||||
%th.centered{:colspan => 2}= t("activerecord.models.maintainer")
|
||||
%th.centered= t("activerecord.attributes.maintainer.updated_at")
|
||||
%tr.search
|
||||
-# TODO: change filter to Backbone.js
|
||||
%th{:colspan => 6, :rowspan => 1}
|
||||
= form_tag platform_maintainers_path(@platform), :method => :get do |f|
|
||||
= text_field_tag('q', params[:q], :placeholder => t("layout.maintainers.search_by_package"), :class => params[:q].present? ? 'black' : 'gray')
|
||||
%input{:type => 'submit', :value => t("layout.search.header")}
|
||||
= button_to t('layout.clear'), {:action => :index} , :method => :get
|
||||
|
||||
%tbody
|
||||
- MaintainerPresenter.present_collection(@maintainers) do |pr|
|
||||
%tr{:class => cycle("odd", "even")}
|
||||
%td= pr.package_link
|
||||
%td= pr.package_type
|
||||
%td= pr.package_version_release
|
||||
%td= pr.maintainer_link
|
||||
%td= pr.maintainer_email_link
|
||||
%td= pr.package_updated_at
|
|
@ -0,0 +1 @@
|
|||
doHandleAbfAssignee(<%= @ret.to_json.html_safe %>);
|
|
@ -0,0 +1,7 @@
|
|||
-set_meta_tags :title => [title_object(@platform), t('layout.maintainers.list_header')]
|
||||
-# FIXME: no these 'base' links!
|
||||
= render 'platforms/base/submenu'
|
||||
= render 'platforms/base/sidebar'
|
||||
= render :partial => 'list', :object => @maintainers
|
||||
= will_paginate @maintainers
|
||||
|
|
@ -2,9 +2,14 @@
|
|||
%td= link_to (build_list.bs_id.present? ? build_list.bs_id : t("layout.build_lists.bs_id_not_set")), build_list
|
||||
%td
|
||||
= build_list.human_status
|
||||
%br
|
||||
- if BuildList::HUMAN_STATUSES[build_list.status].in? [:build_pending, :build_started, :build_publish]
|
||||
%time.js-relative-date{:datetime => build_list.updated_at.strftime("%FT%T%:z"), :title => build_list.updated_at.strftime("%F %T")}
|
||||
= build_list.updated_at.strftime "%F %T"
|
||||
- if build_list.build_started? && ((build_list.project.average_build_time || 0) > 0)
|
||||
\/
|
||||
%time
|
||||
= build_list.project.formatted_average_build_time
|
||||
- if build_list.project.present?
|
||||
%td= link_to build_list.project.name_with_owner, build_list.project
|
||||
%td= build_list_version_link(build_list)
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
.hr
|
||||
%a{:name => 'log'}
|
||||
.log-wrapper
|
||||
.log-header
|
||||
.text-wrap
|
||||
= link_to({:anchor => :log}, {:id => 'log_anchor'}) do
|
||||
%h3= t("layout.build_lists.log.build_log")
|
||||
%span
|
||||
.both
|
||||
.log-body.hidden
|
||||
.reloader
|
||||
%table.options
|
||||
%tr.top
|
||||
%td.first
|
||||
= label_tag :word_wrap do
|
||||
= check_box_tag :word_wrap
|
||||
= t("layout.word_wrap")
|
||||
%td.last{ :class => @build_list.build_started? ? nil : :hidden }
|
||||
= label_tag :autoreload do
|
||||
= check_box_tag :autoreload, true, @build_list.build_started?
|
||||
= t("layout.build_lists.log.autoreload")
|
||||
= select_tag :reload_interval, log_reload_time_options
|
||||
%tr.bottom
|
||||
%td.first
|
||||
= link_to t("layout.build_lists.log.download"), build_list_log_url(:build), :id => :log_url
|
||||
%td.last{ :class => @build_list.build_started? ? nil : :hidden }
|
||||
= label_tag :load_lines do
|
||||
= raw t("layout.build_lists.log.load_lines", :count => select_tag(:load_lines, log_reload_lines_options))
|
||||
.both
|
||||
%textarea.log{ :readonly => :readonly, :wrap => 'off',
|
||||
:data => { :url => log_build_list_path(@build_list), :log_type => :build } }
|
||||
= t("layout.build_lists.log.not_available")
|
||||
|
||||
:javascript
|
||||
$(function() {
|
||||
(function() {
|
||||
var $wrapper = $('div.log-wrapper');
|
||||
var $logBody = $wrapper.children('div.log-body').first();
|
||||
var $logCont = $logBody.children('.log').first();
|
||||
|
||||
var logUrl = $logCont.data('url');
|
||||
var $logHead = $wrapper.children('div.log-header').first();
|
||||
|
||||
var $trigger = $logHead.children('span').first();
|
||||
var $autoload = $('#autoreload');
|
||||
|
||||
var state = $logBody.is(':visible');
|
||||
var t = null; // timer
|
||||
var first_open = true;
|
||||
|
||||
if (state) {
|
||||
$trigger.removeClass('closed');
|
||||
$wrapper.removeClass('inactive')
|
||||
.addClass('active');
|
||||
} else {
|
||||
$trigger.addClass('closed');
|
||||
$logBody.addClass('hidden');
|
||||
$wrapper.removeClass('active')
|
||||
.addClass('inactive');
|
||||
}
|
||||
|
||||
function getLineHeight(element){
|
||||
var temp = document.createElement(element.nodeName);
|
||||
temp.setAttribute("style","margin:0px;padding:0px;font-family:"+element.style.fontFamily+";font-size:"+element.style.fontSize);
|
||||
temp.innerHTML = "test";
|
||||
temp = element.parentNode.appendChild(temp);
|
||||
var ret = temp.clientHeight;
|
||||
temp.parentNode.removeChild(temp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
var loadLog = function() {
|
||||
$.ajax({
|
||||
url: logUrl,
|
||||
type: "GET",
|
||||
dataType: 'json',
|
||||
data: $logCont.data(),
|
||||
beforeSend: function( xhr ) {
|
||||
var token = $('meta[name="csrf-token"]').attr('content');
|
||||
if (token) xhr.setRequestHeader('X-CSRF-Token', token);
|
||||
},
|
||||
success: function(data, textStatus, jqXHR) {
|
||||
var l = $logCont[0];
|
||||
var vScroll = l.scrollTop;
|
||||
var hScroll = l.scrollLeft;
|
||||
var onBottom = Math.abs((l.clientHeight + vScroll - l.scrollHeight)) < getLineHeight(l);
|
||||
|
||||
$logCont.text(data.log);
|
||||
|
||||
$logCont.scrollLeft(hScroll);
|
||||
$logCont.scrollTop((onBottom || first_open) ? l.scrollHeight - l.clientHeight : vScroll);
|
||||
first_open = false;
|
||||
if (!data.building) $autoload.attr({'checked': false}).trigger('change');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var reloadChange = function() {
|
||||
if ($(this).is(':checked')) {
|
||||
first_open = true;
|
||||
loadLog();
|
||||
$logCont.scrollTop($logCont[0].scrollHeight - $logCont[0].clientHeight);
|
||||
t = setInterval(function() {
|
||||
loadLog();
|
||||
}, $('#reload_interval').val());
|
||||
} else {
|
||||
clearInterval(t);
|
||||
}
|
||||
}
|
||||
|
||||
var toggleHandler = function() {
|
||||
state = !state;
|
||||
// if log opened
|
||||
if (state) {
|
||||
if ($autoload.is(':checked')) {
|
||||
$autoload.trigger('change');
|
||||
}
|
||||
} else {
|
||||
clearInterval(t);
|
||||
}
|
||||
$logBody.slideToggle('slow')
|
||||
.toggleClass('hidden');
|
||||
$logHead.toggleClass('active inactive');
|
||||
$trigger.toggleClass('closed');
|
||||
|
||||
window.location.href = $('a#log_anchor').attr('href');
|
||||
}
|
||||
|
||||
$wrapper.on('click', '.log-header > span', toggleHandler);
|
||||
$autoload.on('change', reloadChange);
|
||||
|
||||
$('#word_wrap').on('change', function() {
|
||||
$logCont.attr({'wrap': ($(this).is(':checked')) ? 'soft' : 'off'});
|
||||
});
|
||||
|
||||
$('#reload_interval').on('change', function() {
|
||||
clearInterval(t);
|
||||
if ($autoload.is(':checked')) {
|
||||
t = setInterval($(this).val());
|
||||
}
|
||||
});
|
||||
$('#load_lines').on('change', function() {
|
||||
$logCont.data('load_lines', $(this).val());
|
||||
}).trigger('change');
|
||||
loadLog();
|
||||
|
||||
})();
|
||||
});
|
|
@ -13,7 +13,6 @@
|
|||
link_to("#{@build_list.save_to_platform.name}/#{@build_list.save_to_repository.name}",
|
||||
[@build_list.save_to_platform, @build_list.save_to_repository])]
|
||||
- elsif @build_list.container_path.present?
|
||||
- container_url = "http://#{request.host_with_port}/downloads#{@build_list.container_path}"
|
||||
= link_to container_url, container_url
|
||||
.both
|
||||
|
||||
|
@ -125,8 +124,14 @@
|
|||
var r = new Rosa.Routers.BuildListsAdvisoriesRouter();
|
||||
});
|
||||
|
||||
= submit_tag t("layout.publish"), :confirm => t("layout.confirm"), :name => 'publish' if @build_list.can_publish? && can?(:publish, @build_list)
|
||||
= submit_tag t("layout.reject_publish"), :confirm => t("layout.confirm"), :name => 'reject_publish' if @build_list.can_reject_publish? && can?(:reject_publish, @build_list)
|
||||
- if BuildList::HUMAN_STATUSES[@build_list.status].in? [:build_started, :build_error, :success]
|
||||
= render :partial => 'projects/build_lists/log'
|
||||
|
||||
|
||||
- if (can_publish = @build_list.can_publish? && can?(:publish, @build_list)) || (can_reject = @build_list.can_reject_publish? && can?(:reject_publish, @build_list))
|
||||
.hr
|
||||
= submit_tag t("layout.publish"), :confirm => t("layout.confirm"), :name => 'publish' if can_publish
|
||||
= submit_tag t("layout.reject_publish"), :confirm => t("layout.confirm"), :name => 'reject_publish' if can_reject
|
||||
|
||||
.hr
|
||||
%h3= t("layout.build_lists.items_header")
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
.avatar=image_tag avatar_url(@issue.assignee), :alt => 'avatar'
|
||||
.name=@issue.assignee.fullname
|
||||
.both
|
||||
=link_to(t('layout.issues.label_manage'), '#', :class => "button tmargin10 manage_assignee") if can_manage
|
||||
=link_to(t('layout.issues.assignee_manage'), '#', :class => "button tmargin10 manage_assignee") if can_manage
|
||||
- if can_manage
|
||||
=form_tag search_collaborators_project_issues_path(@project), :id => 'search_user', :method => :get, :style => @issue.persisted? ? 'display:none' : '' do
|
||||
=tracker_search_field(:search_user, t('layout.issues.search_user'))
|
||||
|
@ -47,6 +47,7 @@
|
|||
.both=hidden_field_tag "flag#{label.id}", label.id, :name => "issue[labelings_attributes][#{label.id}][label_id]"
|
||||
=form_for :issue, :url => [@project, @issue], :method => :put, :html => { :class => 'edit_labels issue'} do |f|
|
||||
.manage_labels
|
||||
=hidden_field_tag "update_labels", true
|
||||
- @issue.labels.each do |label|
|
||||
=hidden_field_tag "flag#{label.id}", label.id, :name => "issue[labelings_attributes][#{label.id}][label_id]"
|
||||
- else
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
%span.date=@issue.created_at.to_s(:long)
|
||||
%br/
|
||||
.both
|
||||
.fulltext.view.issue_body=@issue.body
|
||||
.fulltext.view.issue_body=simple_format @issue.body
|
||||
.both
|
||||
%br
|
||||
- if can? :update, @issue
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
.leftlist= f.label :description, t("activerecord.attributes.project.description"), :class => :label
|
||||
.rightlist= f.text_area :description, :class => 'text_field', :cols => 80
|
||||
.both
|
||||
- if ['new', 'create'].include? controller.action_name
|
||||
- if [:new, :create].include? controller.action_name
|
||||
.leftlist= f.label :owner_id, t("activerecord.attributes.project.owner"), :class => :label
|
||||
.rightlist
|
||||
= label_tag t("activerecord.attributes.project.who_owns.me")
|
||||
|
@ -35,7 +35,11 @@
|
|||
.both
|
||||
- if [:edit, :update].include? act
|
||||
.leftlist= t("activerecord.attributes.project.default_branch")
|
||||
.rightlist= f.select :default_branch, options_from_collection_for_select(@project.repo.branches, :name, :name, @project.default_branch), :class => 'sel80', :id => 'branch_selector'
|
||||
.rightlist
|
||||
= f.select :default_branch,
|
||||
options_from_collection_for_select(@project.repo.branches,
|
||||
:name, :name, @project.default_branch),
|
||||
:class => 'sel80', :id => 'branch_selector'
|
||||
.both
|
||||
- if [:edit, :update].include? act
|
||||
.leftlist
|
||||
|
@ -45,7 +49,18 @@
|
|||
%span#niceCheckbox1.niceCheck-main= f.check_box :is_package#, :class => 'niceCheckbox1'
|
||||
.forcheck= t("activerecord.attributes.project.is_package")
|
||||
.both
|
||||
.both
|
||||
.both
|
||||
#maintainer_form{:class => @project.is_package ? '' : 'hidden'}
|
||||
= f.hidden_field :maintainer_id, :value => @project.maintainer_id
|
||||
.leftlist
|
||||
= t("activerecord.attributes.project.maintainer")
|
||||
.rightlist
|
||||
-# TODO: Maybe use something like Chosen with filter and prepopulated
|
||||
-# list of potential maintainers?
|
||||
= autocomplete_field_tag :maintainer_name, @project.maintainer.fullname,
|
||||
autocomplete_maintainers_path(@project.owner, @project),
|
||||
:id_element => '#project_maintainer_id',
|
||||
:placeholder => @project.maintainer.fullname
|
||||
- if [:new, :create].include? act
|
||||
.leftlist= f.label :srpm, t("activerecord.attributes.project.srpm"), :class => :label
|
||||
.rightlist= f.file_field :srpm, :class => 'file_field'
|
||||
|
@ -54,3 +69,7 @@
|
|||
\
|
||||
.rightlist= submit_tag t("layout.save"), :class => 'button'
|
||||
.both
|
||||
:javascript
|
||||
$(function() {
|
||||
( new Rosa.Views.ProjectModifyView ).render();
|
||||
});
|
||||
|
|
|
@ -113,7 +113,8 @@ namespace :update do
|
|||
get("#{current_path}/config/database.yml", "tmp/database.yml")
|
||||
|
||||
remote_settings = YAML::load_file("tmp/database.yml")[rails_env]
|
||||
local_settings = YAML::load_file("config/database.yml")["development"]
|
||||
local_settings = YAML::load_file("config/database.yml")["development"]
|
||||
|
||||
|
||||
run "export PGPASSWORD=#{remote_settings["password"]} && pg_dump --host=#{remote_settings["host"]} --port=#{remote_settings["port"]} --username #{remote_settings["username"]} --file #{current_path}/tmp/#{remote_settings["database"]}_dump -Fc #{remote_settings["database"]}"
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
common: &common
|
||||
project_name: ABF TEST
|
||||
repo_project_name: ABF TEST
|
||||
anonymous_access: false
|
||||
distr_types: ['mdv', 'nau5']
|
||||
wiki_formats:
|
||||
markdown: "Markdown"
|
||||
textile: "Textile"
|
||||
# rdoc: "RDoc"
|
||||
org: "Org-mode"
|
||||
# creole: "Creole"
|
||||
# mediawiki: "MediaWiki"
|
||||
feedback:
|
||||
email:
|
||||
- 'test@example.com'
|
||||
- 'test1@example.com'
|
||||
|
||||
production:
|
||||
<<: *common
|
||||
action_mailer_host: "195.19.76.241"
|
||||
root_path: /share
|
||||
do-not-reply-email: do-not-reply@test.rosalinux.ru
|
||||
project_name: ABF
|
||||
repo_project_name: ABF
|
||||
build_server_ip: 127.0.0.1
|
||||
build_server_port: 12555
|
||||
build_server_path: /xmlrpc
|
||||
product_builder_ip:
|
||||
mdv: 192.168.122.19
|
||||
nau5: 192.168.122.203
|
||||
product_builder_port: 12554
|
||||
product_builder_path: /xmlrpc
|
||||
distr_types: ['mdv', 'nau5']
|
|
@ -1,6 +1,8 @@
|
|||
en:
|
||||
layout:
|
||||
autoreload_page: Update page automatically
|
||||
autoreload_log: Update log every
|
||||
word_wrap: Word wrap
|
||||
read_more: Read more
|
||||
turned_on: on
|
||||
turned_off: off
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
ru:
|
||||
layout:
|
||||
autoreload_page: Автоматически обновлять страницу
|
||||
word_wrap: Перенос строк
|
||||
autoreload_log: Обновлять лог каждые
|
||||
read_more: Читать дальше
|
||||
turned_on: включены
|
||||
turned_off: выключены
|
||||
|
|
|
@ -118,6 +118,21 @@ en:
|
|||
project_not_found: Project not found
|
||||
project_version_not_found: Project version not found
|
||||
|
||||
log:
|
||||
build_log: Build Log
|
||||
not_available: Log not available yet.
|
||||
download: Download log
|
||||
autoreload: Update log every
|
||||
load_lines: Load last %{count} lines
|
||||
|
||||
reload_times:
|
||||
10000: "10 s"
|
||||
30000: "30 s"
|
||||
60000: "1 m"
|
||||
300000: "5 m"
|
||||
600000: "10 m"
|
||||
900000: "15 m"
|
||||
|
||||
flash:
|
||||
build_list:
|
||||
saved: Build list for project version '%{project_version}', platform '%{build_for_platform}' and architecture '%{arch}' has been created successfully
|
||||
|
|
|
@ -117,6 +117,21 @@ ru:
|
|||
project_not_found: проект не найден
|
||||
project_version_not_found: версия не найдена
|
||||
|
||||
log:
|
||||
build_log: Лог сборки
|
||||
not_available: В настоящий момент лог недоступен.
|
||||
download: Загрузить лог
|
||||
autoreload: Обновлять лог каждые
|
||||
load_lines: Загружать последние %{count} строк
|
||||
|
||||
reload_times:
|
||||
10000: "10 сек"
|
||||
30000: "30 сек"
|
||||
60000: "1 мин"
|
||||
300000: "5 мин"
|
||||
600000: "10 мин"
|
||||
900000: "15 мин"
|
||||
|
||||
flash:
|
||||
build_list:
|
||||
saved: Билд лист для версии '%{project_version}', платформы '%{build_for_platform}' и архитектуры '%{arch}' создан успешно
|
||||
|
|
|
@ -41,6 +41,7 @@ en:
|
|||
update_label: Update label
|
||||
label_custom_color: Custom color
|
||||
label_manage: Manage labels
|
||||
assignee_manage: Manage assignee
|
||||
assignee: Assignee
|
||||
search_user: Find user...
|
||||
search_labels: Find labels...
|
||||
|
|
|
@ -40,7 +40,8 @@ ru:
|
|||
new_label: Название новой метки
|
||||
update_label: Обновить метку
|
||||
label_custom_color: Свой цвет
|
||||
label_manage: Управление
|
||||
label_manage: Управление метками
|
||||
assignee_manage: Назначить исполнителя
|
||||
assignee: Исполнитель
|
||||
search_user: Найти пользователя...
|
||||
search_labels: Найти метки...
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
en:
|
||||
layout:
|
||||
maintainers:
|
||||
list_header: Maintainers
|
||||
search_by_package: Search by package name
|
||||
|
||||
flash:
|
||||
maintainer:
|
||||
saved: Maintainer saved
|
||||
created: Maintainer created
|
||||
save_error: Maintainer saves error
|
||||
create_error: Maintainer create error
|
||||
destroyed: Maintainer deleted
|
||||
|
||||
activerecord:
|
||||
models:
|
||||
maintainer: Maintainer
|
||||
attributes:
|
||||
maintainer:
|
||||
package_name: Package
|
||||
package_type: Type
|
||||
created_at: First Update
|
||||
updated_at: Last Update
|
||||
version: Version-Release
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
ru:
|
||||
layout:
|
||||
maintainers:
|
||||
list_header: Майнтейнеры
|
||||
search_by_package: Искать по имени пакета
|
||||
|
||||
flash:
|
||||
maintainer:
|
||||
saved: Майнтейнер успешно сохранен
|
||||
created: Майнтейнер успешно добавлен
|
||||
save_error: Не удалось сохранить майнтейнера
|
||||
create_error: Не удалось создать майнтейнера
|
||||
destroyed: Майнтейнер успешно удален
|
||||
|
||||
activerecord:
|
||||
models:
|
||||
maintainer: Майнтейнер
|
||||
attributes:
|
||||
maintainer:
|
||||
package_name: Пакет
|
||||
package_type: Тип
|
||||
created_at: Создан
|
||||
updated_at: Обновлен
|
||||
version: Версия-Релиз
|
||||
|
|
@ -40,6 +40,7 @@ en:
|
|||
target_platform: Target platform
|
||||
target_architecture: Target architecture
|
||||
members: Members
|
||||
maintainers: Maintainers
|
||||
project: Project
|
||||
arch: Architecture
|
||||
mass_build: Mass build
|
||||
|
|
|
@ -40,6 +40,7 @@ ru:
|
|||
target_platform: Целевая платформа
|
||||
target_architecture: Целевая архитектура
|
||||
members: Участники
|
||||
maintainers: Майнтейнеры
|
||||
arch: Архитектура
|
||||
mass_build: Массовая сборка
|
||||
build_task: Сборочное задание
|
||||
|
|
|
@ -93,6 +93,8 @@ en:
|
|||
group: Group
|
||||
default_branch: Default branch
|
||||
is_package: Project is a package
|
||||
maintainer: Maintainer of project
|
||||
maintainer_id: Maintainer of project
|
||||
errors:
|
||||
project:
|
||||
uname: The name can only use lower case Latin letters (a-z), numbers (0-9) and underscore (_)
|
||||
|
|
|
@ -93,6 +93,8 @@ ru:
|
|||
group: Группа
|
||||
default_branch: Ветка по умолчанию
|
||||
is_package: Проект является пакетом
|
||||
maintainer_id: Майнтейнер проекта
|
||||
maintainer: Майнтейнер проекта
|
||||
errors:
|
||||
project:
|
||||
uname: В имени можно использовать только строчные символы латинского алфавита (a-z), цифры (0-9) и символ нижнего подчеркивания (_)
|
||||
|
|
|
@ -15,6 +15,7 @@ Rosa::Application.routes.draw do
|
|||
get '/forbidden' => 'pages#forbidden', :as => 'forbidden'
|
||||
get '/terms-of-service' => 'pages#tos', :as => 'tos'
|
||||
get '/tour/:id' => 'pages#tour_inside', :as => 'tour_inside', :id => /projects|sources|builds/
|
||||
match '/invite.html' => redirect('/register_requests/new')
|
||||
|
||||
get '/activity_feeds.:format' => 'activity_feeds#index', :as => 'atom_activity_feeds', :format => /atom/
|
||||
if APP_CONFIG['anonymous_access']
|
||||
|
@ -81,7 +82,7 @@ Rosa::Application.routes.draw do
|
|||
resources :products do
|
||||
resources :product_build_lists, :only => [:create, :destroy]
|
||||
end
|
||||
|
||||
resources :maintainers, :only => [:index]
|
||||
end
|
||||
match '/private/:platform_name/*file_path' => 'privates#show'
|
||||
|
||||
|
@ -134,6 +135,7 @@ Rosa::Application.routes.draw do
|
|||
resources :build_lists, :only => [:index, :show, :update] do
|
||||
member do
|
||||
put :cancel
|
||||
get :log
|
||||
end
|
||||
collection { post :search }
|
||||
end
|
||||
|
@ -182,6 +184,7 @@ Rosa::Application.routes.draw do
|
|||
end
|
||||
end
|
||||
# Resource
|
||||
get '/autocomplete_maintainers' => 'projects#autocomplete_maintainers', :as => :autocomplete_maintainers
|
||||
get '/modify' => 'projects#edit', :as => :edit_project
|
||||
put '/' => 'projects#update'
|
||||
delete '/' => 'projects#destroy'
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
class AddNamePlatformIndexToBuildListPackages < ActiveRecord::Migration
|
||||
def change
|
||||
add_index :build_list_packages, [:name,:project_id]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
class AddMaintainerIdToProjects < ActiveRecord::Migration
|
||||
def self.up
|
||||
add_column :projects, :maintainer_id, :integer
|
||||
end
|
||||
|
||||
def self.down
|
||||
remove_column :projects, :maintainer_id
|
||||
end
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
class AddActualToBuildListPackages < ActiveRecord::Migration
|
||||
def self.up
|
||||
add_column :build_list_packages, :actual, :boolean, :default => false
|
||||
add_index :build_list_packages, [:actual, :platform_id]
|
||||
add_index :build_lists, [:project_id, :save_to_repository_id, :build_for_platform_id, :arch_id],
|
||||
:name => :maintainer_search_index
|
||||
end
|
||||
|
||||
def self.down
|
||||
remove_index :build_list_packages, [:actual, :platform_id]
|
||||
remove_column :build_list_packages, :actual
|
||||
remove_index :build_lists, :name => :maintainer_search_index
|
||||
end
|
||||
end
|
29
db/schema.rb
29
db/schema.rb
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20120730214052) do
|
||||
ActiveRecord::Schema.define(:version => 20120822210712) do
|
||||
|
||||
create_table "activity_feeds", :force => true do |t|
|
||||
t.integer "user_id", :null => false
|
||||
|
@ -91,11 +91,14 @@ ActiveRecord::Schema.define(:version => 20120730214052) do
|
|||
t.string "version"
|
||||
t.string "release"
|
||||
t.string "package_type"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.boolean "actual", :default => false
|
||||
end
|
||||
|
||||
add_index "build_list_packages", ["actual", "platform_id"], :name => "index_build_list_packages_on_actual_and_platform_id"
|
||||
add_index "build_list_packages", ["build_list_id"], :name => "index_build_list_packages_on_build_list_id"
|
||||
add_index "build_list_packages", ["name", "project_id"], :name => "index_build_list_packages_on_name_and_project_id"
|
||||
add_index "build_list_packages", ["platform_id"], :name => "index_build_list_packages_on_platform_id"
|
||||
add_index "build_list_packages", ["project_id"], :name => "index_build_list_packages_on_project_id"
|
||||
|
||||
|
@ -131,6 +134,7 @@ ActiveRecord::Schema.define(:version => 20120730214052) do
|
|||
|
||||
add_index "build_lists", ["advisory_id"], :name => "index_build_lists_on_advisory_id"
|
||||
add_index "build_lists", ["arch_id"], :name => "index_build_lists_on_arch_id"
|
||||
add_index "build_lists", ["project_id", "save_to_repository_id", "build_for_platform_id", "arch_id"], :name => "maintainer_search_index"
|
||||
add_index "build_lists", ["bs_id"], :name => "index_build_lists_on_bs_id", :unique => true
|
||||
add_index "build_lists", ["project_id"], :name => "index_build_lists_on_project_id"
|
||||
|
||||
|
@ -169,8 +173,6 @@ ActiveRecord::Schema.define(:version => 20120730214052) do
|
|||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
add_index "projects", ["owner_id"], :name => "index_projects_on_name_and_owner_id_and_owner_type", :unique => true, :case_sensitive => false
|
||||
|
||||
create_table "groups", :force => true do |t|
|
||||
t.integer "owner_id"
|
||||
t.datetime "created_at", :null => false
|
||||
|
@ -325,15 +327,16 @@ ActiveRecord::Schema.define(:version => 20120730214052) do
|
|||
t.text "description"
|
||||
t.string "ancestry"
|
||||
t.boolean "has_issues", :default => true
|
||||
t.boolean "has_wiki", :default => false
|
||||
t.string "srpm_file_name"
|
||||
t.string "srpm_content_type"
|
||||
t.integer "srpm_file_size"
|
||||
t.datetime "srpm_updated_at"
|
||||
t.string "srpm_content_type"
|
||||
t.boolean "has_wiki", :default => false
|
||||
t.string "default_branch", :default => "master"
|
||||
t.boolean "is_package", :default => true, :null => false
|
||||
t.integer "average_build_time", :default => 0, :null => false
|
||||
t.integer "build_count", :default => 0, :null => false
|
||||
t.integer "maintainer_id"
|
||||
end
|
||||
|
||||
add_index "projects", ["owner_id"], :name => "index_projects_on_name_and_owner_id_and_owner_type", :unique => true, :case_sensitive => false
|
||||
|
@ -397,13 +400,13 @@ ActiveRecord::Schema.define(:version => 20120730214052) do
|
|||
|
||||
create_table "users", :force => true do |t|
|
||||
t.string "name"
|
||||
t.string "email", :default => "", :null => false
|
||||
t.string "encrypted_password", :default => "", :null => false
|
||||
t.string "email", :default => "", :null => false
|
||||
t.string "encrypted_password", :limit => 128, :default => "", :null => false
|
||||
t.string "reset_password_token"
|
||||
t.datetime "reset_password_sent_at"
|
||||
t.datetime "remember_created_at"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.text "ssh_key"
|
||||
t.string "uname"
|
||||
t.string "role"
|
||||
|
@ -420,11 +423,11 @@ ActiveRecord::Schema.define(:version => 20120730214052) do
|
|||
t.string "avatar_content_type"
|
||||
t.integer "avatar_file_size"
|
||||
t.datetime "avatar_updated_at"
|
||||
t.integer "failed_attempts", :default => 0
|
||||
t.integer "failed_attempts", :default => 0
|
||||
t.string "unlock_token"
|
||||
t.datetime "locked_at"
|
||||
t.string "authentication_token"
|
||||
t.integer "build_priority", :default => 50
|
||||
t.integer "build_priority", :default => 50
|
||||
end
|
||||
|
||||
add_index "users", ["authentication_token"], :name => "index_users_on_authentication_token"
|
||||
|
|
|
@ -1,22 +1,54 @@
|
|||
require 'highline/import'
|
||||
require 'open-uri'
|
||||
|
||||
desc "Add branch for platform projects"
|
||||
task :add_branch => :environment do
|
||||
src_branch = ENV['SRC_BRANCH'] || 'import_mandriva2011'
|
||||
dst_branch = ENV['DST_BRANCH'] || 'rosa2012lts'
|
||||
|
||||
say "START add branch #{dst_branch} from #{src_branch}"
|
||||
Platform.find_by_name(dst_branch).repositories.each do |r|
|
||||
say "=== Process #{r.name} repo"
|
||||
r.projects.find_each do |p|
|
||||
next if p.repo.branches.map(&:name).include?(dst_branch)
|
||||
say "===== Process #{p.name} project"
|
||||
tmp_path = Rails.root.join('tmp', p.name)
|
||||
system("git clone #{p.path} #{tmp_path}")
|
||||
system("cd #{tmp_path} && git checkout remotes/origin/#{src_branch} || git checkout master")
|
||||
system("cd #{tmp_path} && git checkout -b #{dst_branch} && git push origin HEAD")
|
||||
FileUtils.rm_rf tmp_path
|
||||
end
|
||||
namespace :add_branch do
|
||||
desc 'Fork project branch'
|
||||
task :fork_branch, :path, :src_branch, :dst_branch do |t, args|
|
||||
tmp_path = File.join Dir.tmpdir, "#{Time.now.to_i}#{rand(1000)}"
|
||||
system("git clone #{args[:path]} #{tmp_path}")
|
||||
system("cd #{tmp_path} && git checkout remotes/origin/#{args[:src_branch]} || git checkout master")
|
||||
system("cd #{tmp_path} && git checkout -b #{args[:dst_branch]} && git push origin HEAD")
|
||||
FileUtils.rm_rf tmp_path
|
||||
end
|
||||
|
||||
desc "Add branch for platform projects"
|
||||
task :platform => :environment do
|
||||
src_branch = ENV['SRC_BRANCH'] || 'import_mandriva2011'
|
||||
dst_branch = ENV['DST_BRANCH'] || 'rosa2012lts'
|
||||
say "START add branch #{dst_branch} from #{src_branch}"
|
||||
Platform.find_by_name(dst_branch).repositories.each do |r|
|
||||
say "=== Process #{r.name} repo"
|
||||
r.projects.find_each do |p|
|
||||
next if p.repo.branches.map(&:name).include?(dst_branch)
|
||||
say "===== Process #{p.name} project"
|
||||
Rake::Task['add_branch:fork_branch'].execute(:path => p.path, :src_branch => src_branch, :dst_branch => dst_branch)
|
||||
end
|
||||
end
|
||||
say 'DONE'
|
||||
end
|
||||
|
||||
desc "Add branch for owner projects by list"
|
||||
task :list => :environment do
|
||||
source = ENV['SOURCE'] || 'https://dl.dropbox.com/u/984976/texlive.txt'
|
||||
owner = User.find_by_uname(ENV['OWNER']) || Group.find_by_uname!(ENV['OWNER'] || 'import')
|
||||
platform = Platform.find_by_name!(ENV['PLATFORM'] || 'rosa2012.1')
|
||||
repo = platform.repositories.find_by_name!(ENV['REPO'] || 'main')
|
||||
src_branch = ENV['SRC_BRANCH'] || 'import_cooker'
|
||||
dst_branch = ENV['DST_BRANCH'] || 'rosa2012.1'
|
||||
say "START fork from #{src_branch} to #{dst_branch} branch using #{source} for #{owner.uname}. Add to repo '#{platform.name}/#{repo.name}'."
|
||||
open(source).readlines.each do |name|
|
||||
name.chomp!; name.strip!
|
||||
print "Fork branch for '#{name}'... "
|
||||
if p = Project.find_by_name_and_owner_type_and_owner_id(name, owner.class.to_s, owner.id)
|
||||
# Rake::Task['add_branch:fork_branch'].execute(:path => p.path, :src_branch => src_branch, :dst_branch => dst_branch)
|
||||
system "bundle exec rake add_branch:fork_branch[#{p.path},#{src_branch},#{dst_branch}] -s RAILS_ENV=#{Rails.env} > /dev/null 2>&1"
|
||||
print 'Ok!'
|
||||
repo.projects << p rescue print ' Add to repo failed!'
|
||||
else
|
||||
print 'Not Found!'
|
||||
end
|
||||
puts
|
||||
end
|
||||
say 'DONE'
|
||||
end
|
||||
say 'DONE'
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
namespace :buildlist do
|
||||
|
||||
|
||||
namespace :clear do
|
||||
desc 'Remove outdated BuildLists and MassBuilds'
|
||||
task :outdated => :environment do
|
||||
|
@ -17,4 +17,32 @@ namespace :buildlist do
|
|||
say "Outdated BuildLists and MassBuilds was successfully removed"
|
||||
end
|
||||
end
|
||||
|
||||
namespace :packages do
|
||||
# TODO Maybe do it in migration, because it's just a single query?
|
||||
desc 'Actualize packages for all platforms'
|
||||
task :actualize => :environment do
|
||||
|
||||
say "Updating packages"
|
||||
packages = BuildList::Package.joins( %q{
|
||||
JOIN (
|
||||
SELECT
|
||||
name AS j_pn,
|
||||
package_type AS j_pt,
|
||||
platform_id AS j_plid,
|
||||
MAX(created_at) AS j_ca
|
||||
FROM
|
||||
build_list_packages
|
||||
GROUP BY
|
||||
j_pn, j_pt, j_plid
|
||||
) AS lastmaints
|
||||
ON
|
||||
j_pn = name
|
||||
AND j_pt = package_type
|
||||
AND j_plid = platform_id
|
||||
AND j_ca = created_at
|
||||
} ).update_all(:actual => true)
|
||||
say "'Actual' setted to #{packages} packages"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -77,13 +77,15 @@ namespace :import do
|
|||
|
||||
namespace :sync do
|
||||
desc "Sync all repos"
|
||||
task :all do
|
||||
system("bundle exec rake import:sync:run RELEASE=official/2011 PLATFORM=mandriva2011 REPOSITORY=main")
|
||||
system("bundle exec rake import:sync:run RELEASE=official/2011 PLATFORM=mandriva2011 REPOSITORY=contrib")
|
||||
system("bundle exec rake import:sync:run RELEASE=official/2011 PLATFORM=mandriva2011 REPOSITORY=non-free")
|
||||
task :all => :environment do
|
||||
# system("bundle exec rake import:sync:run RELEASE=official/2011 PLATFORM=mandriva2011 REPOSITORY=main")
|
||||
# system("bundle exec rake import:sync:run RELEASE=official/2011 PLATFORM=mandriva2011 REPOSITORY=contrib")
|
||||
# system("bundle exec rake import:sync:run RELEASE=official/2011 PLATFORM=mandriva2011 REPOSITORY=non-free")
|
||||
system("bundle exec rake import:sync:run RELEASE=devel/cooker PLATFORM=cooker REPOSITORY=main")
|
||||
system("bundle exec rake import:sync:run RELEASE=devel/cooker PLATFORM=cooker REPOSITORY=contrib")
|
||||
system("bundle exec rake import:sync:run RELEASE=devel/cooker PLATFORM=cooker REPOSITORY=non-free")
|
||||
system("bundle exec rake import:sync:run SOURCE=rsync://mirror.yandex.ru/fedora-epel/6/SRPMS/ DESTINATION=#{File.join(APP_CONFIG['root_path'], 'mirror.yandex.ru', 'fedora-epel', '6', 'SRPMS')} PLATFORM=server_personal REPOSITORY=main OWNER=server BRANCH=import")
|
||||
system("bundle exec rake import:sync:run SOURCE=rsync://rh-mirror.redhat.com/redhat/linux/enterprise/6Server/en/os/SRPMS/ DESTINATION=#{File.join(APP_CONFIG['root_path'], 'rh-mirror.redhat.com', 'redhat', 'linux', 'enterprise', '6Server', 'en', 'os', 'SRPMS')} PLATFORM=server_personal REPOSITORY=main OWNER=server BRANCH=import")
|
||||
end
|
||||
|
||||
task :run => [:rsync, :parse]
|
||||
|
@ -92,7 +94,7 @@ namespace :import do
|
|||
task :rsync => :environment do
|
||||
release = ENV['RELEASE'] || 'official/2011'
|
||||
repository = ENV['REPOSITORY'] || 'main'
|
||||
source = "rsync://mirror.yandex.ru/mandriva/#{release}/SRPMS/#{repository}/"
|
||||
source = ENV['SOURCE'] || "rsync://mirror.yandex.ru/mandriva/#{release}/SRPMS/#{repository}/"
|
||||
destination = ENV['DESTINATION'] || File.join(APP_CONFIG['root_path'], 'mirror.yandex.ru', 'mandriva', release, 'SRPMS', repository)
|
||||
say "START rsync projects (*.src.rpm) from '#{source}' to '#{destination}' (#{Time.now.utc})"
|
||||
if system "rsync -rtv --delete --exclude='backports/*' --exclude='testing/*' #{source} #{destination}" # --include='*.src.rpm'
|
||||
|
@ -108,29 +110,34 @@ namespace :import do
|
|||
release = ENV['RELEASE'] || 'official/2011'
|
||||
platform = Platform.find_by_name(ENV['PLATFORM'] || "mandriva2011")
|
||||
repository = platform.repositories.find_by_name(ENV['REPOSITORY'] || 'main')
|
||||
source = ENV['SOURCE'] || File.join(APP_CONFIG['root_path'], 'mirror.yandex.ru', 'mandriva', release, 'SRPMS', repository.name)
|
||||
source = ENV['DESTINATION'] || File.join(APP_CONFIG['root_path'], 'mirror.yandex.ru', 'mandriva', release, 'SRPMS', repository.name, '{release,updates}')
|
||||
owner = Group.find_or_create_by_uname(ENV['OWNER'] || 'import') {|g| g.name = g.uname; g.owner = User.first}
|
||||
branch = "import_#{platform.name}"
|
||||
branch = ENV['BRANCH'] || "import_#{platform.name}"
|
||||
|
||||
say "START (#{Time.now.utc})"
|
||||
Dir[File.join source, '{release,updates}', '*.src.rpm'].each do |srpm_file|
|
||||
Dir[File.join source, '*.src.rpm'].each do |srpm_file|
|
||||
print "Processing '#{srpm_file}'... "
|
||||
if name = `rpm -q --qf '[%{Name}]' -p #{srpm_file}` and $?.success? and name.present? and
|
||||
version = `rpm -q --qf '[%{Version}-%{Release}]' -p #{srpm_file}` and $?.success? and version.present?
|
||||
project_import = ProjectImport.find_by_name_and_platform_id(name, platform.id) || ProjectImport.by_name(name).where(:platform_id => platform.id).first || ProjectImport.new(:name => name, :platform_id => platform.id)
|
||||
if version != project_import.version.to_s and File.mtime(srpm_file) > project_import.file_mtime
|
||||
unless project = project_import.project
|
||||
if project = repository.projects.find_by_name(name) || repository.projects.by_name(name).first # fallback to speedup
|
||||
print "Found project #{project.owner.uname}/#{project.name} in #{platform.name}/#{repository.name}. "
|
||||
elsif scoped = Project.where(:owner_id => owner.id, :owner_type => owner.class) and
|
||||
project = scoped.find_by_name(name) || scoped.by_name(name).first
|
||||
repository.projects << project
|
||||
print "Add project #{project.owner.uname}/#{project.name} to #{platform.name}/#{repository.name}. "
|
||||
else
|
||||
description = ::Iconv.conv('UTF-8//IGNORE', 'UTF-8', `rpm -q --qf '[%{Description}]' -p #{srpm_file}`)
|
||||
project = Project.create!(:name => name, :description => description) {|p| p.owner = owner}
|
||||
repository.projects << project
|
||||
print "Create project #{project.owner.uname}/#{project.name} at #{platform.name}/#{repository.name}. "
|
||||
if platform.personal? # search project through owner # used for testhat
|
||||
project = Project.find_or_create_by_name_and_owner_type_and_owner_id(name, owner.class.to_s, owner.id)
|
||||
print "Use project #{project.owner.uname}/#{project.name}. "
|
||||
else # search project through repository
|
||||
if project = repository.projects.find_by_name(name) || repository.projects.by_name(name).first # fallback to speedup
|
||||
print "Found project #{project.owner.uname}/#{project.name} in #{platform.name}/#{repository.name}. "
|
||||
elsif scoped = Project.where(:owner_id => owner.id, :owner_type => owner.class) and
|
||||
project = scoped.find_by_name(name) || scoped.by_name(name).first
|
||||
repository.projects << project
|
||||
print "Add project #{project.owner.uname}/#{project.name} to #{platform.name}/#{repository.name}. "
|
||||
else
|
||||
description = ::Iconv.conv('UTF-8//IGNORE', 'UTF-8', `rpm -q --qf '[%{Description}]' -p #{srpm_file}`)
|
||||
project = Project.create!(:name => name, :description => description) {|p| p.owner = owner}
|
||||
repository.projects << project
|
||||
print "Create project #{project.owner.uname}/#{project.name} at #{platform.name}/#{repository.name}. "
|
||||
end
|
||||
end
|
||||
end
|
||||
project.import_srpm(srpm_file, branch)
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
namespace :project do
|
||||
|
||||
namespace :maintainer do
|
||||
desc 'Set maintainer to owner (or to owners owner if owner is a group) to projects'
|
||||
task :set_to_owner => :environment do
|
||||
projects = Project.scoped
|
||||
count = projects.count
|
||||
say "Setting maintainer to all projects (#{count})"
|
||||
percent_per_batch = 100 * 1000 / count
|
||||
i = 1
|
||||
|
||||
projects.find_in_batches do |batch|
|
||||
ActiveRecord::Base.transaction do
|
||||
batch.each do |proj|
|
||||
maintainer_id = (proj.owner_type == 'User') ? proj.owner_id : proj.owner.owner_id
|
||||
proj.maintainer_id = maintainer_id
|
||||
proj.save
|
||||
end
|
||||
end
|
||||
say "#{percent_per_batch * i}% done."
|
||||
i += 1
|
||||
end
|
||||
say "100% done"
|
||||
end
|
||||
end
|
||||
task :maintainer => 'maintainer:set_to_owner'
|
||||
|
||||
end
|
|
@ -0,0 +1,47 @@
|
|||
# -*- encoding : utf-8 -*-
|
||||
require 'spec_helper'
|
||||
|
||||
shared_examples_for 'guest user' do
|
||||
|
||||
# Only one action for now here
|
||||
guest_actions = [:index]
|
||||
|
||||
if APP_CONFIG['anonymous_access']
|
||||
guest_actions.each do |action|
|
||||
it "should be able to perform #{ action } action" do
|
||||
get action, :platform_id => @platform.id
|
||||
response.should be_success
|
||||
end
|
||||
end
|
||||
else # non-anonymous access
|
||||
guest_actions.each do |action|
|
||||
it "should not be able to perform #{ action } action" do
|
||||
get action, :platform_id => @platform.id
|
||||
response.should redirect_to(new_user_session_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe Platforms::MaintainersController do
|
||||
before(:each) do
|
||||
stub_symlink_methods
|
||||
|
||||
@platform = FactoryGirl.create(:platform)
|
||||
@platform.visibility = 'open'
|
||||
|
||||
# JS format is the primary target for this callback
|
||||
@assignee_rq = { :platform_id => @platform.id, :package => 'test', :format => 'js' }
|
||||
end
|
||||
|
||||
context 'for guest' do
|
||||
it_should_behave_like 'guest user'
|
||||
|
||||
it 'should not be able to get api' do
|
||||
get :assignee, @assignee_rq
|
||||
response.response_code.should == 403
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ describe Platforms::PlatformsController do
|
|||
:platform_type => 'main',
|
||||
:distrib_type => APP_CONFIG['distr_types'].first
|
||||
}}
|
||||
end
|
||||
end
|
||||
|
||||
context 'for guest' do
|
||||
|
||||
|
|
Loading…
Reference in New Issue