diff --git a/.gitignore b/.gitignore
index f64162cf5..eba8c3256 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,8 +19,11 @@
.DS_Store
._*
*~
+*.sw*
+*.patch
config/newrelic.yml
public/sitemap*.xml.gz
+spec/examples.txt
dump.rdb
db/sphinx/*
config/development.sphinx.conf
diff --git a/.ruby-version b/.ruby-version
index 73462a5a1..aa485ac6f 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-2.5.1
+ext-ruby-2.5.1
diff --git a/Gemfile b/Gemfile
index d4570a278..7c5aaed83 100644
--- a/Gemfile
+++ b/Gemfile
@@ -44,6 +44,9 @@ gem 'browser'
gem 'http_accept_language'
# gem 'molinillo', require: false
+# view
+gem 'slim'
+
group :production, :development do
gem 'redis'
end
diff --git a/Gemfile.lock b/Gemfile.lock
index c0aadde24..97329ccca 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -378,6 +378,9 @@ GEM
simplecov-html (0.10.2)
sitemap_generator (6.0.1)
builder (~> 3.0)
+ slim (3.0.9)
+ temple (>= 0.7.6, < 0.9)
+ tilt (>= 1.3.3, < 2.1)
spring (2.0.2)
activesupport (>= 4.2)
spring-commands-rspec (1.0.4)
@@ -399,6 +402,7 @@ GEM
net-scp (>= 1.1.2)
net-ssh (>= 2.8.0)
swagger-blocks (2.0.2)
+ temple (0.8.0)
text (1.3.1)
thor (0.20.0)
thread_safe (0.3.6)
@@ -514,6 +518,7 @@ DEPENDENCIES
sidekiq
simplecov
sitemap_generator
+ slim
spring
spring-commands-rspec
spring-commands-rubocop
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 46b20359f..1c9ab932e 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -13,3 +13,20 @@
//= require rails-ujs
//= require turbolinks
//= require_tree .
+//
+
+let changeHref = (e) => {
+ let index = e.target.options.selectedIndex,
+ url = e.target.options[index].getAttribute('value')
+
+ document.querySelectorAll('a.download').forEach((a) => {
+ let href = a.getAttribute('data-path')
+
+ a.setAttribute('href', url + href)
+ })
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ let input = document.querySelector('.mirror-url')
+ input.addEventListener('change', changeHref)
+})
diff --git a/app/assets/javascripts/br/local.js.erb b/app/assets/javascripts/br/local.js.erb
index e5ee1e7f4..33db6e05b 100644
--- a/app/assets/javascripts/br/local.js.erb
+++ b/app/assets/javascripts/br/local.js.erb
@@ -1,3 +1,4 @@
+/*
$(document).ready(function() {
$('#topMain').toggle(function() {
$('#topMain').attr("src", "<%= asset_path 'restore.gif' %>");
@@ -39,3 +40,4 @@ $(document).ready(function() {
$('#topBranchesDiv').show();
});
});
+*/
diff --git a/app/assets/javascripts/en/local.js.erb b/app/assets/javascripts/en/local.js.erb
index e5ee1e7f4..33db6e05b 100644
--- a/app/assets/javascripts/en/local.js.erb
+++ b/app/assets/javascripts/en/local.js.erb
@@ -1,3 +1,4 @@
+/*
$(document).ready(function() {
$('#topMain').toggle(function() {
$('#topMain').attr("src", "<%= asset_path 'restore.gif' %>");
@@ -39,3 +40,4 @@ $(document).ready(function() {
$('#topBranchesDiv').show();
});
});
+*/
diff --git a/app/assets/javascripts/ru/local.js.erb b/app/assets/javascripts/ru/local.js.erb
index f6ff3b628..08627f01e 100644
--- a/app/assets/javascripts/ru/local.js.erb
+++ b/app/assets/javascripts/ru/local.js.erb
@@ -1,3 +1,4 @@
+/*
$(document).ready(function() {
$('#topMain').toggle(function() {
$('#topMain').attr("src", "<%= asset_path 'restore.gif' %>");
@@ -39,3 +40,4 @@ $(document).ready(function() {
$('#topBranchesDiv').show();
});
});
+*/
diff --git a/app/assets/javascripts/uk/local.js.erb b/app/assets/javascripts/uk/local.js.erb
index 5a4c482b0..5561abbd8 100644
--- a/app/assets/javascripts/uk/local.js.erb
+++ b/app/assets/javascripts/uk/local.js.erb
@@ -1,3 +1,4 @@
+/*
$(document).ready(function() {
$('#topMain').toggle(function() {
$('#topMain').attr("src", "<%= asset_path 'restore.gif' %>");
@@ -39,3 +40,4 @@ $(document).ready(function() {
$('#topBranchesDiv').show();
});
});
+*/
diff --git a/app/assets/stylesheets/srpm.scss b/app/assets/stylesheets/srpm.scss
new file mode 100644
index 000000000..9a7e9affc
--- /dev/null
+++ b/app/assets/stylesheets/srpm.scss
@@ -0,0 +1,14 @@
+tr.arch {
+ & > td {
+ padding-top: 1em;
+ }
+
+ td.package {
+ border-bottom: dotted 1px #aaa;
+ padding-right: 1em;
+ }
+
+ td.size {
+ text-align: right;
+ }
+}
diff --git a/app/controllers/srpms_controller.rb b/app/controllers/srpms_controller.rb
index bcb13806e..9ac1b1ecc 100644
--- a/app/controllers/srpms_controller.rb
+++ b/app/controllers/srpms_controller.rb
@@ -62,10 +62,7 @@ def get
@srpm = @branch.srpms.where(name: params[:id]).includes(:branch).first!
@mirrors = Mirror.where(branch_id: @branch).where("protocol != 'rsync'").order('mirrors.order_id ASC')
@allsrpms = AllSrpmsWithName.new(params[:id]).search.decorate
- @i586 = @srpm.packages.where(arch: 'i586').order('packages.name ASC')
- @noarch = @srpm.packages.where(arch: 'noarch').order('packages.name ASC')
- @x86_64 = @srpm.packages.where(arch: 'x86_64').order('packages.name ASC')
- @arm = @srpm.packages.where(arch: 'arm').order('packages.name ASC')
+ @packages = @srpm.packages.order('packages.name ASC').group("packages.arch, packages.id").includes(:branch).decorate
@all_bugs = AllBugsForSrpm.new(@srpm).decorate
@opened_bugs = OpenedBugsForSrpm.new(@srpm).decorate
end
diff --git a/app/decorators/package_decorator.rb b/app/decorators/package_decorator.rb
index a6b82c4c8..03d047af6 100644
--- a/app/decorators/package_decorator.rb
+++ b/app/decorators/package_decorator.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class PackageDecorator < Draper::Decorator
+ include ActionView::Helpers::NumberHelper
+
delegate_all
def as_json(*)
@@ -27,4 +29,16 @@ def as_json(*)
updated_at: updated_at.iso8601
}
end
+
+ def href
+ "http://ftp.altlinux.org/pub/distributions/ALTLinux#{path}"
+ end
+
+ def human_size
+ number_to_human_size(size)
+ end
+
+ def path
+ "#{branch.path}/files/#{arch}/RPMS/#{filename}"
+ end
end
diff --git a/app/decorators/packages_decorator.rb b/app/decorators/packages_decorator.rb
new file mode 100644
index 000000000..167e62d07
--- /dev/null
+++ b/app/decorators/packages_decorator.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class PackagesDecorator < Draper::CollectionDecorator
+ def arched_packages
+ self.group_by { |x| x.arch }
+ end
+end
diff --git a/app/lib/rpm/base.rb b/app/lib/rpm/base.rb
index 0b163ffd6..9b35572dc 100644
--- a/app/lib/rpm/base.rb
+++ b/app/lib/rpm/base.rb
@@ -8,6 +8,10 @@ class Base
attr_reader :file
+ def rpm
+ self.class
+ end
+
def initialize(file)
@file = file
end
@@ -94,6 +98,14 @@ def md5
@md5 ||= Digest::MD5.file(file).hexdigest
end
+ def has_valid_md5?
+ output = rpm.exec(
+ line: " -K #{rpm.no_signature_key} :file",
+ file: file)
+
+ output && !(output.strip.split(': ').last.force_encoding('utf-8') !~ rpm.valid_signature_answer)
+ end
+
private
def read_int(tag)
@@ -106,21 +118,53 @@ def read_time(tag)
end
def read(tag)
- output = read_raw(tag)
-
- output = nil if ['(none)', ''].include?(output)
+ output = rpm.exec(
+ line: '-qp --queryformat=:tag :file',
+ tag: tag,
+ file: file)
output
end
- def read_raw(tag)
- cocaine = Cocaine::CommandLine.new('rpm', '-qp --queryformat=:tag :file', environment: { 'LANG' => 'C' })
+ class << self
+ def no_signature_key
+ @no_signature_key ||= exec('--nosignature').present? && '--nosignature' || '--nogpg'
+ end
+
+ def use_common_signature?
+ no_signature_key == '--nosignature'
+ end
+
+ def valid_signature_answer
+ use_common_signature? && /sha1 md5 O[KК]/ || /md5 O[KК]/
+ end
+
+ def hash_of args
+ if args.is_a?(String)
+ { line: args }
+ elsif args.is_a?(Hash)
+ args
+ else
+ raise
+ end
+ end
+
+ def exec args
+ a_hash = hash_of(args)
+
+ wrapper = Cocaine::CommandLine.new('rpm', a_hash[:line], environment: { 'LANG' => 'C' })
+
+ result = wrapper.run(a_hash)
+ result !~ /\A(\(none\)|)\z/ && result || nil
+ rescue Cocaine::CommandNotFoundError
+ Rails.logger.info('rpm command not found')
+
+ nil
+ rescue Cocaine::ExitStatusError
+ Rails.logger.info('rpm exit status non zero')
- cocaine.run(tag: tag, file: file)
- rescue Cocaine::CommandNotFoundError
- Rails.logger.info('rpm command not found')
- rescue Cocaine::ExitStatusError
- Rails.logger.info('rpm exit status non zero')
+ nil
+ end
end
- end
+ end
end
diff --git a/app/models/package.rb b/app/models/package.rb
index 27d057f31..9977ae607 100644
--- a/app/models/package.rb
+++ b/app/models/package.rb
@@ -17,6 +17,8 @@ class Package < ApplicationRecord
has_many :conflicts, dependent: :destroy
+ has_one :branch, through: :srpm
+
validates :groupname, presence: true
validates :md5, presence: true
diff --git a/app/models/rpm_check_md5.rb b/app/models/rpm_check_md5.rb
index a25f6cb32..d399ecd15 100644
--- a/app/models/rpm_check_md5.rb
+++ b/app/models/rpm_check_md5.rb
@@ -2,11 +2,6 @@
class RPMCheckMD5
def self.check_md5(file)
- output = `export LANG=C && rpm -K --nosignature #{ file }`
- if !output.empty? && output.chop.split(': ').last == 'sha1 md5 OK'
- true
- else
- false
- end
+ RPM::Base.new(file).has_valid_md5?
end
end
diff --git a/app/models/srpm.rb b/app/models/srpm.rb
index f9b21b02c..d1a745b4c 100644
--- a/app/models/srpm.rb
+++ b/app/models/srpm.rb
@@ -44,6 +44,7 @@ class Srpm < ApplicationRecord
validates :groupname, presence: true
validates :md5, presence: true
+ validates_presence_of :buildtime
# delegate :name, to: :branch, prefix: true
diff --git a/app/views/shared/_arches.html.slim b/app/views/shared/_arches.html.slim
new file mode 100644
index 000000000..b7f97fbaf
--- /dev/null
+++ b/app/views/shared/_arches.html.slim
@@ -0,0 +1,13 @@
+- arches.each do |arch, packages|
+ tr.arch
+ td
+ b = "#{arch}: "
+ - packages.each.with_index do |package, index|
+ tr
+ td.package
+ b
+ = "· "
+ a.news.download { id="pack_#{index + 1}" href=package.href data={path: package.path} } = package.filename
+ = " (md5: #{package.md5})"
+ td.size
+ b = package.human_size
diff --git a/app/views/srpms/get.html.erb b/app/views/srpms/get.html.erb
index 127035dce..938a39d5a 100644
--- a/app/views/srpms/get.html.erb
+++ b/app/views/srpms/get.html.erb
@@ -38,59 +38,12 @@
<%= link_to _('Main'), srpm_path(@srpm.branch, @srpm), class: 'news', title: _('information about SRPM') %> <%= link_to _('Changelog'), changelog_srpm_path(@srpm.branch, @srpm), class: 'news', title: _('full changelog') %> <%= link_to _('Spec'), spec_srpm_path(@srpm.branch, @srpm), class: 'news', title: _('spec') %> <%= link_to _('Patches'), srpm_patches_path(@srpm.branch, @srpm), class: 'news', title: _('patches') %> <%= link_to _('Sources'), srpm_sources_path(@srpm.branch, @srpm), class: 'news', title: _('sources') %> <%= _('Download') %> <%= link_to _('Gear'), gear_srpm_path(@srpm.branch, @srpm), class: 'news', title: _('this package in gear repositories') %> <%= link_to _('Bugs and FR (%s/%s)') % [@opened_bugs.count, @all_bugs.count], bugs_srpm_path(@srpm), class: 'news', title: _('list of bugs and feature requests') %> <%= link_to _('Repocop'), repocop_srpm_path(@srpm), class: 'news', title: _('repocop bugreports') %>
-
<%= _('Choose a mirror:') %>
-