app/models/repository.rb

Summary

Maintainability
A
0 mins
Test Coverage
class Repository < ApplicationRecord

  has_many :repositories_services_associations
  has_many :services, through: :repositories_services_associations
  has_many :systems, through: :services
  has_many :products, -> { distinct }, through: :services

  scope :only_installer_updates, -> { where(installer_updates: true) }
  scope :only_mirroring_enabled, -> { where(mirroring_enabled: true) }
  scope :only_fully_mirrored, -> { where(mirroring_enabled: true).where.not(last_mirrored_at: nil) }
  scope :only_enabled, -> { where(enabled: true) }
  scope :only_custom, -> { where(scc_id: nil) }
  scope :only_scc, -> { where.not(scc_id: nil) }
  scope :exclude_installer_updates, -> { where(installer_updates: false) }

  validates :name, presence: true
  validates :external_url, presence: true
  validates :local_path, presence: true
  validates :friendly_id, presence: true

  before_destroy :ensure_destroy_possible

  class << self

    def remove_suse_repos_without_tokens!
      where(auth_token: nil).where('external_url LIKE ?', 'https://updates.suse.com%').delete_all
    end

    # Mangles remote repo URL to make a nicer local path, see specs for examples
    def make_local_path(url)
      uri = URI(url)
      path = uri.path.to_s
      path.gsub!(%r{^/repo}, '') if (uri.hostname == 'updates.suse.com')
      (path == '') ? '/' : path
    end

    def make_friendly_id(input)
      sanitized_input = input.to_s.strip.gsub(/\s+/, '-').gsub(/[^[:alnum:]\-_]/, '').downcase

      # Don't modify numeric input (scc_ids) and, if the friendly_id doesn't exist yet, allow it without a postfix
      return sanitized_input if /^[0-9]+$/.match?(sanitized_input) || Repository.default_scoped.where(friendly_id: sanitized_input).empty?

      # The requested friendly_id was taken, so we need to find a working number to append
      append_base = "#{sanitized_input}-"
      regexp = /(.*)-(\d+)\z/

      potential_conflicts = Repository.default_scoped.select(:friendly_id).where('friendly_id LIKE ?', "#{append_base}%").collect(&:friendly_id)
      max = potential_conflicts.map do |conflict|
        match = conflict.match(regexp)
        sql = sanitize_sql_array(['SELECT ? = ?', sanitized_input, match[1].to_s])
        connection.execute(sql).first[0] == 1 ? match[2].to_i : 0
      end.max
      max ||= 0

      "#{append_base}#{max + 1}"
    end

  end

  def refresh_timestamp!
    touch(:last_mirrored_at)
  end

  def change_mirroring!(mirroring_enabled)
    update_column(:mirroring_enabled, mirroring_enabled)
  end

  def custom?
    scc_id.nil?
  end

  private

  def ensure_destroy_possible
    throw(:abort) unless custom?
  end

end