importing.rb revision 5ad775859282bb9988faac1bcdbb72ab1012a1bd
282f31b2b7ad4ca69287402d6d3a91a280bcb15eJulian Kornberger#
282f31b2b7ad4ca69287402d6d3a91a280bcb15eJulian Kornberger# States:
282f31b2b7ad4ca69287402d6d3a91a280bcb15eJulian Kornberger# * pending - Job is enqueued.
282f31b2b7ad4ca69287402d6d3a91a280bcb15eJulian Kornberger# * fetching - Fetching new commits from the remote repository.
282f31b2b7ad4ca69287402d6d3a91a280bcb15eJulian Kornberger# * processing - Inserting fetched commits into the local database-
282f31b2b7ad4ca69287402d6d3a91a280bcb15eJulian Kornberger# * done - Everthing is fine, nothing to do-
282f31b2b7ad4ca69287402d6d3a91a280bcb15eJulian Kornberger# * failed - Something has gone wrong.
282f31b2b7ad4ca69287402d6d3a91a280bcb15eJulian Kornberger#
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornbergermodule Repository::Importing
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger extend ActiveSupport::Concern
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger SOURCE_TYPES = %w( git svn )
282f31b2b7ad4ca69287402d6d3a91a280bcb15eJulian Kornberger STATES = %w( pending fetching processing done failed )
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger IMPORT_INTERVAL = 15.minutes
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger included do
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger include StateUpdater
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger scope :with_source, where("source_type IS NOT null")
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger # Ready for pulling
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger scope :outdated, ->{
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger with_source
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger .where("imported_at IS NULL or imported_at < ?", IMPORT_INTERVAL.ago )
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger .where(state: 'done')
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger }
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger validates_inclusion_of :state, in: STATES
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa validates_with SourceTypeValidator, if: :remote?
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa before_validation ->{ detect_source_type }
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger after_create ->{ async_remote :clone }, if: :remote?
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger end
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger def remote?
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger source_address?
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger end
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger
282f31b2b7ad4ca69287402d6d3a91a280bcb15eJulian Kornberger # do not allow new actions in specific states
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger def locked?
282f31b2b7ad4ca69287402d6d3a91a280bcb15eJulian Kornberger !%w( done failed ).include?(state)
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger end
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger # enqueues a pull/clone job
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger def async_remote(method)
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger raise "object is #{state}" if locked?
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger update_state! 'pending'
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger async :remote_send, method
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger end
93ff918a7a1656d812f27a767a976ea33da0921fJulian Kornberger
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger # executes a pull/clone job
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger def remote_send(method)
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger # build arguments
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger args = []
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger args << source_address if method == 'clone'
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger # build method name
93ff918a7a1656d812f27a767a976ea33da0921fJulian Kornberger method = method.to_s
5379e11f2c6c49c6df4872d6a55f2ff390969e66Julian Kornberger method += '_svn' if source_type == 'svn'
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger do_or_set_failed do
282f31b2b7ad4ca69287402d6d3a91a280bcb15eJulian Kornberger update_state! 'fetching'
93ff918a7a1656d812f27a767a976ea33da0921fJulian Kornberger result = git.send(method, *args)
282f31b2b7ad4ca69287402d6d3a91a280bcb15eJulian Kornberger
282f31b2b7ad4ca69287402d6d3a91a280bcb15eJulian Kornberger update_state! 'processing'
5ad775859282bb9988faac1bcdbb72ab1012a1bdJulian Kornberger suspended_save_ontologies \
5ad775859282bb9988faac1bcdbb72ab1012a1bdJulian Kornberger start_oid: result.current,
5ad775859282bb9988faac1bcdbb72ab1012a1bdJulian Kornberger stop_oid: result.previous,
5ad775859282bb9988faac1bcdbb72ab1012a1bdJulian Kornberger walk_order: Rugged::SORT_REVERSE
282f31b2b7ad4ca69287402d6d3a91a280bcb15eJulian Kornberger
7b1e12286a360e4bfd9b54f97c2ad1d1a561c77dJulian Kornberger self.imported_at = Time.now
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger update_state! 'done'
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger
93ff918a7a1656d812f27a767a976ea33da0921fJulian Kornberger result
93ff918a7a1656d812f27a767a976ea33da0921fJulian Kornberger end
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger end
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger module ClassMethods
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger # creates a new repository and imports the contents from the remote repository
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger def import_remote(type, user, source, name, params={})
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger raise ArgumentError, "invalid source type: #{type}" unless SOURCE_TYPES.include?(type)
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger raise Repository::ImportError, "#{source} is not a #{type} repository" unless GitRepository.send "is_#{type}_repository?", source
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger params[:name] = name
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger params[:source_type] = type
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger params[:source_address] = source
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger
89575ed6ea1f9c9058164005c0c8a64e8aeae3a4Julian Kornberger r = Repository.new(params)
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger r.user = user
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger r.save!
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger r
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger end
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornberger end
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa protected
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa def detect_source_type
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa if GitRepository.is_git_repository?(source_address)
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa self.source_type = 'git'
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa elsif GitRepository.is_svn_repository?(source_address)
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa self.source_type = 'svn'
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa end
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa end
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa class SourceTypeValidator < ActiveModel::Validator
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa def validate(record)
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa if record.remote? && !record.source_type.present?
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa record.errors[:source_address] = "not a valid remote repository (types supported: #{SOURCE_TYPES.join(', ')})"
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa record.errors[:source_type] = "not present"
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa end
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa end
39d0ed9f8e3c74205b66e86abcf317c6a56900ccEugen Kuksa end
5422b48ab5841a2909cd9e53905dae4cd8418f0aJulian Kornbergerend