aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/version.rb')
-rw-r--r--app/models/version.rb165
1 files changed, 165 insertions, 0 deletions
diff --git a/app/models/version.rb b/app/models/version.rb
new file mode 100644
index 0000000..1dc28f8
--- /dev/null
+++ b/app/models/version.rb
@@ -0,0 +1,165 @@
+class Version
+ include Elasticsearch::Persistence::Model
+ include Kkuleomi::Store::Model
+ include Kkuleomi::Store::Models::VersionImport
+
+ index_name "packages-#{Rails.env}"
+
+ attribute :version, String, mapping: { index: 'not_analyzed' }
+ attribute :package, String, mapping: { index: 'not_analyzed' }
+ attribute :atom, String, mapping: { index: 'not_analyzed' }
+ attribute :sort_key, Integer, mapping: { index: 'not_analyzed' }
+ attribute :slot, String, mapping: { index: 'not_analyzed' }
+ attribute :subslot, String, mapping: { index: 'not_analyzed' }
+ attribute :eapi, String, mapping: { index: 'not_analyzed' }
+ attribute :keywords, String, mapping: { index: 'not_analyzed' }
+ attribute :masks, Array, default: [], mapping: { type: 'object' }
+ attribute :use, String, default: [], mapping: { index: 'not_analyzed' }
+ attribute :restrict, String, default: [], mapping: { index: 'not_analyzed' }
+ attribute :properties, String, default: [], mapping: { index: 'not_analyzed' }
+ attribute :metadata_hash, String, mapping: { index: 'not_analyzed' }
+
+ # Returns the keywording state on a given architecture
+ #
+ # @param [String] arch Architecture to query
+ # @return [Symbol] :stable, :testing, :unavailable, :unknown
+ def keyword(arch)
+ @keyword_info_cache ||= parse_keywords keywords
+
+ if @keyword_info_cache[:arches].key? arch
+ @keyword_info_cache[:arches][arch]
+ else
+ if @keyword_info_cache[:exclude_all]
+ :unavailable
+ else
+ :unknown
+ end
+ end
+ end
+
+ # Returns the effective keyword on a given architecture, accounting for masks
+ #
+ # @param [String] arch Architecture to query
+ # @return [Symbol] Keyword status
+ def effective_keyword(arch)
+ if is_masked?(arch)
+ :masked
+ else
+ keyword(arch)
+ end
+ end
+
+ # Returns the masks that apply to the given architecture
+ #
+ def mask(arch)
+ masks.reject do |m|
+ if m['arch'] == '*'
+ false
+ else
+ m['arch'] != arch
+ end
+ end
+ end
+
+ # Checks the masks whether one sounds like a package removal.
+ def removal_pending?
+ return false if masks.empty?
+
+ masks.each do |m|
+ if m['reason'].include?('removal') || m['reason'].include?('Removal')
+ return true
+ end
+ end
+
+ false
+ end
+
+ def is_masked?(arch = nil)
+ !mask(arch).empty?
+ end
+
+ # Returns supported USE flags categorized by local, global, and USE_EXPAND
+ # Typically called in the import phase, not live
+ #
+ # @return [Hash]
+ def useflags
+ @useflags ||= calc_useflags
+ end
+
+ # Retrieves the most widely used USE flags by all versions
+ # Note that packages with many versions are over-represented
+ def self.get_popular_useflags(n = 50)
+ search(
+ query: { match_all: {} },
+ aggs: {
+ group_by_flag: {
+ terms: {
+ field: 'use',
+ size: n
+ }
+ }
+ },
+ size: 0
+ ).response.aggregations['group_by_flag'].buckets
+ end
+
+ # Parses a keyword array and assigns tags for each arch
+ #
+ # @param [Array<String>] keywords Input keywords
+ # @return [Hash] Parsed keywords
+ def parse_keywords(keywords)
+ res = { exclude_all: false, arches: {} }
+ return res unless keywords
+
+ keywords.each do |kw|
+ if kw == '-*'
+ res[:exclude_all] = true
+ next
+ end
+
+ if kw.start_with? '-'
+ res[:arches][kw[1..-1]] = :unavailable
+ next
+ end
+
+ if kw.start_with? '~'
+ res[:arches][kw[1..-1]] = :testing
+ next
+ end
+
+ res[:arches][kw] = :stable
+ end
+
+ res
+ end
+
+ private
+
+ def calc_useflags
+ result = { local: {}, global: {}, use_expand: {} }
+
+ local_flag_map = Useflag.local_for(atom.gsub("-#{version}", ''))
+ local_flags = local_flag_map.keys
+
+ use.sort.each do |flag|
+ if local_flags.include? flag
+ result[:local][flag] = local_flag_map[flag].to_hsh
+ else
+ useflag = Useflag.find_by(:name, flag)
+
+ # This should not happen, but let's be sure
+ next unless useflag
+
+ if useflag.scope == 'global'
+ result[:global][useflag.name] = useflag.to_hsh
+ elsif useflag.scope == 'use_expand'
+ prefix = useflag.use_expand_prefix.upcase
+ result[:use_expand][prefix] ||= {}
+ result[:use_expand][prefix][useflag.name.gsub(useflag.use_expand_prefix + '_', '')] = useflag.to_hsh
+ end
+ end
+ end
+
+ result
+ end
+end