Merge pull request #433 from abf/rosa-build:432-repositories-with-empty-metadata
#432: Personal repositories should be created with empty metadata
This commit is contained in:
commit
bdeef6f460
|
@ -0,0 +1,70 @@
|
|||
class CreateEmptyMetadataJob < Struct.new(:class_name, :id)
|
||||
@queue = :low
|
||||
|
||||
def perform
|
||||
case class_name
|
||||
when Platform.name
|
||||
create_empty_metadata_for_platform
|
||||
when Repository.name
|
||||
create_empty_metadata_for_repository Repository.find(id)
|
||||
end
|
||||
end
|
||||
|
||||
def self.perform(class_name, id)
|
||||
new(class_name, id).perform
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_empty_metadata_for_platform
|
||||
platform = Platform.main.opened.find id
|
||||
@platforms = [platform]
|
||||
repositories = Repository.joins(:platform).
|
||||
where(platforms: { platform_type: Platform::TYPE_PERSONAL })
|
||||
repositories.find_each do |r|
|
||||
create_empty_metadata_for_repository r
|
||||
end
|
||||
end
|
||||
|
||||
def create_empty_metadata_for_repository(repository)
|
||||
@platforms = [repository.platform] if repository.platform.main?
|
||||
platforms.each do |platform|
|
||||
arch_names.each do |arch_name|
|
||||
%w(release updates).each do |type|
|
||||
path = "#{ repository.platform.path }/repository/"
|
||||
path << "#{ platform.name }/" if repository.platform.personal?
|
||||
path << "#{ arch_name }/#{ repository.name }/#{ type }"
|
||||
create_empty_metadata(platform, path)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_empty_metadata(platform, path)
|
||||
case platform.distrib_type
|
||||
when 'rhel'
|
||||
path << '/repodata/'
|
||||
when 'mdv'
|
||||
path << '/media_info/'
|
||||
else
|
||||
return
|
||||
end
|
||||
if Dir["#{ path }/*"].empty?
|
||||
system "mkdir -p -m 0777 #{ path }"
|
||||
system "cp -f #{ empty_metadatas(platform) }/* #{ path }/"
|
||||
end
|
||||
end
|
||||
|
||||
def empty_metadatas(platform)
|
||||
Rails.root.join('public', 'metadatas', platform.distrib_type).to_s
|
||||
end
|
||||
|
||||
def arch_names
|
||||
@arch_names ||= Arch.pluck(:name)
|
||||
end
|
||||
|
||||
def platforms
|
||||
@platforms ||= Platform.main.opened.to_a
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
module EmptyMetadata
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
after_create :create_empty_metadata
|
||||
end
|
||||
|
||||
def create_empty_metadata
|
||||
return if is_a?(Platform) && ( personal? || hidden? )
|
||||
Resque.enqueue(CreateEmptyMetadataJob, self.class.name, id)
|
||||
end
|
||||
|
||||
end
|
|
@ -7,17 +7,17 @@ module PersonalRepository
|
|||
|
||||
def create_personal_repository
|
||||
begin
|
||||
pl = own_platforms.build
|
||||
pl.owner = self
|
||||
pl.name = "#{self.uname}_personal"
|
||||
pl.description = "#{self.uname}_personal"
|
||||
pl.platform_type = 'personal'
|
||||
pl.distrib_type = APP_CONFIG['distr_types'].first
|
||||
pl.visibility = 'open'
|
||||
pl = own_platforms.build
|
||||
pl.owner = self
|
||||
pl.name = "#{self.uname}_personal"
|
||||
pl.description = "#{self.uname}_personal"
|
||||
pl.platform_type = Platform::TYPE_PERSONAL
|
||||
pl.distrib_type = APP_CONFIG['distr_types'].first
|
||||
pl.visibility = Platform::VISIBILITY_OPEN
|
||||
pl.save!
|
||||
|
||||
rep = pl.repositories.build
|
||||
rep.name = 'main'
|
||||
rep = pl.repositories.build
|
||||
rep.name = 'main'
|
||||
rep.description = 'main'
|
||||
rep.save!
|
||||
rescue Exception => e
|
||||
|
|
|
@ -6,12 +6,21 @@ class Platform < ActiveRecord::Base
|
|||
include RegenerationStatus
|
||||
include Owner
|
||||
include EventLoggable
|
||||
include EmptyMetadata
|
||||
|
||||
CACHED_CHROOT_PRODUCT_NAME = 'cached-chroot'
|
||||
AUTOMATIC_METADATA_REGENERATIONS = %w(day week)
|
||||
VISIBILITIES = [
|
||||
VISIBILITY_OPEN = 'open',
|
||||
VISIBILITY_HIDDEN = 'hidden'
|
||||
]
|
||||
NAME_PATTERN = /[\w\-\.]+/
|
||||
HUMAN_STATUSES = HUMAN_STATUSES.clone.freeze
|
||||
TYPES = [
|
||||
TYPE_PERSONAL = 'personal',
|
||||
TYPE_MAIN = 'main'
|
||||
]
|
||||
|
||||
CACHED_CHROOT_PRODUCT_NAME = 'cached-chroot'
|
||||
AUTOMATIC_METADATA_REGENERATIONS = %w(day week)
|
||||
VISIBILITIES = %w(open hidden)
|
||||
NAME_PATTERN = /[\w\-\.]+/
|
||||
HUMAN_STATUSES = HUMAN_STATUSES.clone.freeze
|
||||
|
||||
belongs_to :parent, class_name: 'Platform', foreign_key: 'parent_platform_id'
|
||||
belongs_to :owner, polymorphic: true
|
||||
|
@ -32,16 +41,36 @@ class Platform < ActiveRecord::Base
|
|||
|
||||
has_many :mass_builds, foreign_key: :save_to_platform_id
|
||||
|
||||
validates :description, presence: true
|
||||
validates :visibility, presence: true, inclusion: { in: VISIBILITIES }
|
||||
validates :automatic_metadata_regeneration, inclusion: { in: AUTOMATIC_METADATA_REGENERATIONS }, allow_blank: true
|
||||
validates :name, uniqueness: {case_sensitive: false}, presence: true, format: { with: /\A#{NAME_PATTERN}\z/ }
|
||||
validates :distrib_type, presence: true, inclusion: { in: APP_CONFIG['distr_types'] }
|
||||
validates :description,
|
||||
presence: true
|
||||
|
||||
validates :visibility,
|
||||
presence: true,
|
||||
inclusion: { in: VISIBILITIES }
|
||||
|
||||
validates :platform_type,
|
||||
presence: true,
|
||||
inclusion: { in: TYPES }
|
||||
|
||||
validates :automatic_metadata_regeneration,
|
||||
inclusion: { in: AUTOMATIC_METADATA_REGENERATIONS },
|
||||
allow_blank: true
|
||||
|
||||
validates :name,
|
||||
uniqueness: { case_sensitive: false },
|
||||
presence: true,
|
||||
format: { with: /\A#{NAME_PATTERN}\z/ }
|
||||
|
||||
validates :distrib_type,
|
||||
presence: true,
|
||||
inclusion: { in: APP_CONFIG['distr_types'] }
|
||||
|
||||
validate -> {
|
||||
if released_was && !released
|
||||
errors.add(:released, I18n.t('flash.platform.released_status_can_not_be_changed'))
|
||||
end
|
||||
}
|
||||
|
||||
validate -> {
|
||||
if personal? && (owner_id_changed? || owner_type_changed?)
|
||||
errors.add :owner, I18n.t('flash.platform.owner_can_not_be_changed')
|
||||
|
@ -54,22 +83,32 @@ class Platform < ActiveRecord::Base
|
|||
after_update :freeze_platform_and_update_repos
|
||||
after_update :update_owner_relation
|
||||
|
||||
after_create -> { symlink_directory unless hidden? }
|
||||
after_create -> { symlink_directory unless hidden? }
|
||||
after_destroy -> { remove_symlink_directory unless hidden? }
|
||||
|
||||
scope :search_order, -> { order(:name) }
|
||||
scope :search, ->(q) { where("#{table_name}.name ILIKE ?", "%#{q.to_s.strip}%") }
|
||||
scope :by_visibilities, ->(v) { where(visibility: v) }
|
||||
scope :opened, -> { where(visibility: 'open') }
|
||||
scope :hidden, -> { where(visibility: 'hidden') }
|
||||
scope :by_type, ->(type) { where(platform_type: type) if type.present? }
|
||||
scope :main, -> { by_type('main') }
|
||||
scope :personal, -> { by_type('personal') }
|
||||
scope :waiting_for_regeneration, -> { where(status: WAITING_FOR_REGENERATION) }
|
||||
scope :search_order, -> { order(:name) }
|
||||
scope :search, -> (q) { where("#{table_name}.name ILIKE ?", "%#{q.to_s.strip}%") }
|
||||
scope :by_visibilities, -> (v) { where(visibility: v) }
|
||||
scope :opened, -> { where(visibility: VISIBILITY_OPEN) }
|
||||
scope :hidden, -> { where(visibility: VISIBILITY_HIDDEN) }
|
||||
scope :by_type, -> (type) { where(platform_type: type) if type.present? }
|
||||
scope :main, -> { by_type(TYPE_MAIN) }
|
||||
scope :personal, -> { by_type(TYPE_PERSONAL) }
|
||||
scope :waiting_for_regeneration, -> { where(status: WAITING_FOR_REGENERATION) }
|
||||
|
||||
accepts_nested_attributes_for :platform_arch_settings, allow_destroy: true
|
||||
attr_accessible :name, :distrib_type, :parent_platform_id, :platform_type, :owner, :visibility, :description, :released, :platform_arch_settings_attributes, :automatic_metadata_regeneration
|
||||
attr_readonly :name, :distrib_type, :parent_platform_id, :platform_type
|
||||
attr_accessible :name,
|
||||
:distrib_type,
|
||||
:parent_platform_id,
|
||||
:platform_type,
|
||||
:owner,
|
||||
:visibility,
|
||||
:description,
|
||||
:released,
|
||||
:platform_arch_settings_attributes,
|
||||
:automatic_metadata_regeneration
|
||||
|
||||
attr_readonly :name, :distrib_type, :parent_platform_id, :platform_type
|
||||
|
||||
state_machine :status, initial: :ready do
|
||||
|
||||
|
@ -144,15 +183,15 @@ class Platform < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def hidden?
|
||||
visibility == 'hidden'
|
||||
visibility == VISIBILITY_HIDDEN
|
||||
end
|
||||
|
||||
def personal?
|
||||
platform_type == 'personal'
|
||||
platform_type == TYPE_PERSONAL
|
||||
end
|
||||
|
||||
def main?
|
||||
platform_type == 'main'
|
||||
platform_type == TYPE_MAIN
|
||||
end
|
||||
|
||||
def base_clone(attrs = {}) # :description, :name, :owner
|
||||
|
@ -175,10 +214,10 @@ class Platform < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def change_visibility
|
||||
if !hidden?
|
||||
update_attributes(visibility: 'hidden')
|
||||
if hidden?
|
||||
update_attributes(visibility: VISIBILITY_OPEN)
|
||||
else
|
||||
update_attributes(visibility: 'open')
|
||||
update_attributes(visibility: VISIBILITY_HIDDEN)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -190,6 +229,7 @@ class Platform < ActiveRecord::Base
|
|||
File.open(File.join(symlink_path, "#{name}.#{arch.name}.list"), 'w') {|f| f.write(str) }
|
||||
end
|
||||
end
|
||||
later :symlink_directory, queue: :middle
|
||||
|
||||
def remove_symlink_directory
|
||||
system("rm -Rf #{symlink_path}")
|
||||
|
@ -262,7 +302,6 @@ class Platform < ActiveRecord::Base
|
|||
system("mkdir -p -m 0777 #{build_path([name, 'repository'])}")
|
||||
end
|
||||
|
||||
|
||||
def build_path(dir)
|
||||
File.join(APP_CONFIG['root_path'], 'platforms', dir)
|
||||
end
|
||||
|
|
|
@ -3,6 +3,7 @@ class Repository < ActiveRecord::Base
|
|||
friendly_id :name, use: [:finders]
|
||||
|
||||
include EventLoggable
|
||||
include EmptyMetadata
|
||||
|
||||
LOCK_FILE_NAMES = { sync: '.sync.lock', repo: '.repo.lock' }
|
||||
SORT = { 'base' => 1, 'main' => 2, 'contrib' => 3, 'non-free' => 4, 'restricted' => 5 }
|
||||
|
@ -28,7 +29,7 @@ class Repository < ActiveRecord::Base
|
|||
scope :recent, -> { order(:name) }
|
||||
scope :main, -> { where(name: %w(main base)) }
|
||||
|
||||
before_destroy :detele_directory
|
||||
before_destroy :detele_directory
|
||||
|
||||
attr_accessible :name,
|
||||
:description,
|
||||
|
@ -66,6 +67,7 @@ class Repository < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
later :clone_relations, loner: true, queue: :low
|
||||
|
||||
def add_projects(list, user)
|
||||
current_ability = Ability.new(user)
|
||||
list.lines.each do |line|
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
.rightlist= f.select :distrib_type, options_for_select(APP_CONFIG['distr_types'])
|
||||
.both
|
||||
|
||||
.leftlist= f.label :visibility, class: :label
|
||||
.rightlist= f.select :visibility, options_for_select(Platform::VISIBILITIES.map{ |v| [t("activerecord.attributes.platform.visibility_types.#{v}"), v] })
|
||||
.both
|
||||
|
||||
-#.leftlist= f.label :parent, class: :label
|
||||
.rightlist= f.collection_select :parent_platform_id, Platform.all, :id, :description, include_blank: true
|
||||
.both
|
||||
|
@ -26,24 +30,25 @@
|
|||
= hidden_field_tag 'admin_id', @admin_id, id: 'admin_id_field'
|
||||
.both
|
||||
|
||||
%h3= t('layout.platform_arch_settings.extra_settings')
|
||||
- if ['edit', 'update'].include? controller.action_name
|
||||
%h3= t('layout.platform_arch_settings.extra_settings')
|
||||
|
||||
%table.tablesorter{cellpadding: "0", cellspacing: "0"}
|
||||
%thead
|
||||
%tr
|
||||
%th.lpadding16= t("activerecord.models.arch")
|
||||
%th.lpadding16= t("activerecord.attributes.platform_arch_setting.default")
|
||||
%th.lpadding16= t("activerecord.attributes.platform_arch_setting.time_living")
|
||||
%tbody
|
||||
- platform_arch_settings(@platform).each do |setting|
|
||||
%tr{class: cycle("odd", "even")}
|
||||
= f.fields_for :platform_arch_settings, setting do |s_form|
|
||||
%td
|
||||
= setting.arch.name
|
||||
= s_form.hidden_field :arch_id
|
||||
%td.center= s_form.check_box :default, class: 'check_box'
|
||||
%td.right= s_form.text_field :time_living, value: setting.time_living / 60, class: 'text_field', size: 10
|
||||
.both
|
||||
%table.tablesorter{cellpadding: "0", cellspacing: "0"}
|
||||
%thead
|
||||
%tr
|
||||
%th.lpadding16= t("activerecord.models.arch")
|
||||
%th.lpadding16= t("activerecord.attributes.platform_arch_setting.default")
|
||||
%th.lpadding16= t("activerecord.attributes.platform_arch_setting.time_living")
|
||||
%tbody
|
||||
- platform_arch_settings(@platform).each do |setting|
|
||||
%tr{class: cycle("odd", "even")}
|
||||
= f.fields_for :platform_arch_settings, setting do |s_form|
|
||||
%td
|
||||
= setting.arch.name
|
||||
= s_form.hidden_field :arch_id
|
||||
%td.center= s_form.check_box :default, class: 'check_box'
|
||||
%td.right= s_form.text_field :time_living, value: setting.time_living / 60, class: 'text_field', size: 10
|
||||
.both
|
||||
|
||||
.button_block
|
||||
= f.submit t('layout.save'), data: {'disable-with' => t('layout.saving')}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
145c9f725bdcc3ba2f7955b102bce09b synthesis.hdlist.cz
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<repomd xmlns="http://linux.duke.edu/metadata/repo" xmlns:rpm="http://linux.duke.edu/metadata/rpm">
|
||||
<revision>1412059094</revision>
|
||||
<data type="filelists">
|
||||
<checksum type="sha256">31ad3f2fbe7608dea8c8c7952373ca917bfe00fc729e1f4ecb29fb43c2064f1d</checksum>
|
||||
<open-checksum type="sha256">bf9808b81cb2dbc54b4b8e35adc584ddcaa73bd81f7088d73bf7dbbada961310</open-checksum>
|
||||
<location href="repodata/31ad3f2fbe7608dea8c8c7952373ca917bfe00fc729e1f4ecb29fb43c2064f1d-filelists.xml.gz"/>
|
||||
<timestamp>1412059094</timestamp>
|
||||
<size>186</size>
|
||||
<open-size>125</open-size>
|
||||
</data>
|
||||
<data type="other">
|
||||
<checksum type="sha256">a9769a64dee317b6b67923a4f6c173419e43720cb60f6411d5525382df28605f</checksum>
|
||||
<open-checksum type="sha256">e0ed5e0054194df036cf09c1a911e15bf2a4e7f26f2a788b6f47d53e80717ccc</open-checksum>
|
||||
<location href="repodata/a9769a64dee317b6b67923a4f6c173419e43720cb60f6411d5525382df28605f-other.xml.gz"/>
|
||||
<timestamp>1412059094</timestamp>
|
||||
<size>182</size>
|
||||
<open-size>121</open-size>
|
||||
</data>
|
||||
<data type="primary">
|
||||
<checksum type="sha256">a44e7259aa2c562a139498175f1fc64f8e98d3fda7fa22444b4121cd6e246fb7</checksum>
|
||||
<open-checksum type="sha256">e1e2ffd2fb1ee76f87b70750d00ca5677a252b397ab6c2389137a0c33e7b359f</open-checksum>
|
||||
<location href="repodata/a44e7259aa2c562a139498175f1fc64f8e98d3fda7fa22444b4121cd6e246fb7-primary.xml.gz"/>
|
||||
<timestamp>1412059094</timestamp>
|
||||
<size>195</size>
|
||||
<open-size>167</open-size>
|
||||
</data>
|
||||
</repomd>
|
|
@ -0,0 +1,97 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe CreateEmptyMetadataJob do
|
||||
|
||||
before { stub_symlink_methods }
|
||||
subject { BuildLists::CleanBuildrootJob }
|
||||
|
||||
context 'create_empty_metadata' do
|
||||
let(:job) { CreateEmptyMetadataJob.new }
|
||||
let(:platform) { FactoryGirl.build(:platform) }
|
||||
let(:path) { platform.path }
|
||||
|
||||
it 'creates metadata for rhel platform' do
|
||||
platform.distrib_type = 'rhel'
|
||||
job.send :create_empty_metadata, platform, path.dup
|
||||
|
||||
expect(Dir["#{ path }/repodata/*"]).to be_present
|
||||
expect(Dir["#{ path }/media_info/*"]).to be_empty
|
||||
end
|
||||
|
||||
it 'creates metadata for mdv platform' do
|
||||
platform.distrib_type = 'mdv'
|
||||
job.send :create_empty_metadata, platform, path.dup
|
||||
|
||||
expect(Dir["#{ path }/media_info/*"]).to be_present
|
||||
expect(Dir["#{ path }/repodata/*"]).to be_empty
|
||||
end
|
||||
|
||||
it 'does nothing for other platforms' do
|
||||
platform.distrib_type = 'test'
|
||||
job.send :create_empty_metadata, platform, path.dup
|
||||
|
||||
expect(Dir["#{ path }/media_info/*"]).to be_empty
|
||||
expect(Dir["#{ path }/repodata/*"]).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'create_empty_metadata_for_repository' do
|
||||
let(:job) { CreateEmptyMetadataJob.new }
|
||||
let(:repository) { FactoryGirl.build(:repository) }
|
||||
let(:platform) { repository.platform }
|
||||
|
||||
before do
|
||||
allow(job).to receive(:arch_names).and_return(%w(i586 x86_64))
|
||||
end
|
||||
|
||||
it 'repository of main platform' do
|
||||
paths = <<-STR
|
||||
#{ platform.path }/repository/i586/#{ repository.name }/release
|
||||
#{ platform.path }/repository/i586/#{ repository.name }/updates
|
||||
#{ platform.path }/repository/x86_64/#{ repository.name }/release
|
||||
#{ platform.path }/repository/x86_64/#{ repository.name }/updates
|
||||
STR
|
||||
paths.split("\n").each do |path|
|
||||
expect(job).to receive(:create_empty_metadata).with(platform, path.strip)
|
||||
end
|
||||
|
||||
job.send :create_empty_metadata_for_repository, repository
|
||||
end
|
||||
|
||||
it 'repository of personal platform' do
|
||||
platform.platform_type = Platform::TYPE_PERSONAL
|
||||
Platform.stub_chain(:main, :opened).and_return([platform])
|
||||
paths = <<-STR
|
||||
#{ platform.path }/repository/#{ platform.name }/i586/#{ repository.name }/release
|
||||
#{ platform.path }/repository/#{ platform.name }/i586/#{ repository.name }/updates
|
||||
#{ platform.path }/repository/#{ platform.name }/x86_64/#{ repository.name }/release
|
||||
#{ platform.path }/repository/#{ platform.name }/x86_64/#{ repository.name }/updates
|
||||
STR
|
||||
paths.split("\n").each do |path|
|
||||
expect(job).to receive(:create_empty_metadata).with(platform, path.strip)
|
||||
end
|
||||
|
||||
job.send :create_empty_metadata_for_repository, repository
|
||||
end
|
||||
end
|
||||
|
||||
context 'create_empty_metadata_for_platform' do
|
||||
let(:platform) { FactoryGirl.build(:platform, id: 123) }
|
||||
let(:repository1) { FactoryGirl.build(:personal_repository) }
|
||||
let(:repository2) { FactoryGirl.build(:personal_repository) }
|
||||
let(:job) { CreateEmptyMetadataJob.new('Platform', 123) }
|
||||
|
||||
before do
|
||||
Platform.stub_chain(:main, :opened, :find).and_return(platform)
|
||||
Repository.stub_chain(:joins, :where, :find_each).and_yield(repository1).and_yield(repository2)
|
||||
end
|
||||
|
||||
it 'creates metadata for all personal repositories' do
|
||||
expect(job).to receive(:create_empty_metadata_for_repository).with(repository1)
|
||||
expect(job).to receive(:create_empty_metadata_for_repository).with(repository2)
|
||||
|
||||
job.send :create_empty_metadata_for_platform
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -48,6 +48,9 @@ end
|
|||
def stub_symlink_methods
|
||||
allow_any_instance_of(Platform).to receive(:symlink_directory).and_return(true)
|
||||
allow_any_instance_of(Platform).to receive(:remove_symlink_directory).and_return(true)
|
||||
|
||||
allow_any_instance_of(Platform).to receive(:create_empty_metadata).and_return(true)
|
||||
allow_any_instance_of(Repository).to receive(:create_empty_metadata).and_return(true)
|
||||
end
|
||||
|
||||
Resque.inline = true
|
||||
|
|
Loading…
Reference in New Issue