importing.rb revision 08070fff5598f6d5d7662e321becf59f18d00176
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen#
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen# States:
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen# * pending - Job is enqueued.
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen# * fetching - Fetching new commits from the remote repository.
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen# * processing - Inserting fetched commits into the local database-
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen# * done - Everthing is fine, nothing to do-
1ed1ad066e4aa313e33dafedb892fb84946cacebTimo Sirainen# * failed - Something has gone wrong.
146240408e677e99e579d1feed92689585cc25d4Timo Sirainen#
b1dd6be436e887774b94965ebe9af6d04179c227Timo Sirainenmodule Repository::Importing
9844b5359f5cab77e4c31a7ac9e4a60a0073929eTimo Sirainen extend ActiveSupport::Concern
4073f0dbf3277f981a8fcee3b89ea15aaf380a7fTimo Sirainen
b200bc3875fa06d42c8619865cc306c3297fcaccAki Tuomi SOURCE_TYPES = %w( git svn )
b200bc3875fa06d42c8619865cc306c3297fcaccAki Tuomi STATES = %w( pending fetching processing done failed )
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen
b200bc3875fa06d42c8619865cc306c3297fcaccAki Tuomi IMPORT_INTERVAL = 15.minutes
b200bc3875fa06d42c8619865cc306c3297fcaccAki Tuomi
0aac625db5e6e179c8ee7420a12ab300d6b178edTimo Sirainen included do
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen include StateUpdater
e5224c0589916fb22f95f959326cf4b6221715b0Timo Sirainen
ca44a6ba994aaa3231a20ef6e046dfd97a8dcd2dTimo Sirainen scope :with_source, where("source_type IS NOT null")
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen # Ready for pulling
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen scope :outdated, ->{
ca44a6ba994aaa3231a20ef6e046dfd97a8dcd2dTimo Sirainen with_source
419cf63077e755935ce105747d6ebc67b7d38a7fTimo Sirainen .where("imported_at IS NULL or imported_at < ?", IMPORT_INTERVAL.ago )
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen .where(state: 'done')
b200bc3875fa06d42c8619865cc306c3297fcaccAki Tuomi }
ca44a6ba994aaa3231a20ef6e046dfd97a8dcd2dTimo Sirainen
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen validates_inclusion_of :state, in: STATES
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen validates_with SourceTypeValidator, if: :remote?
1ed1ad066e4aa313e33dafedb892fb84946cacebTimo Sirainen
1ed1ad066e4aa313e33dafedb892fb84946cacebTimo Sirainen before_validation ->{ detect_source_type }
146240408e677e99e579d1feed92689585cc25d4Timo Sirainen after_create ->{ async_remote :clone }, if: :remote?
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen end
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen def remote?
1ed1ad066e4aa313e33dafedb892fb84946cacebTimo Sirainen source_address?
1ed1ad066e4aa313e33dafedb892fb84946cacebTimo Sirainen end
cbe49ba128638e63395aedaa2144087c89835633Timo Sirainen
cbe49ba128638e63395aedaa2144087c89835633Timo Sirainen def convert_to_local!
source_address = nil
source_type = nil
save!
end
# do not allow new actions in specific states
def locked?
!%w( done failed ).include?(state)
end
# enqueues a pull/clone job
def async_remote(method)
raise "object is #{state}" if locked?
update_state! 'pending'
async :remote_send, method
end
# executes a pull/clone job
def remote_send(method)
# build arguments
args = []
args << source_address if method == 'clone'
# build method name
method = method.to_s
method += '_svn' if source_type == 'svn'
do_or_set_failed do
update_state! 'fetching'
result = git.send(method, *args)
update_state! 'processing'
suspended_save_ontologies \
start_oid: result.current,
stop_oid: result.previous,
walk_order: Rugged::SORT_REVERSE
self.imported_at = Time.now
update_state! 'done'
result
end
end
module ClassMethods
# creates a new repository and imports the contents from the remote repository
def import_remote(type, user, source, name, params={})
raise ArgumentError, "invalid source type: #{type}" unless SOURCE_TYPES.include?(type)
raise Repository::ImportError, "#{source} is not a #{type} repository" unless GitRepository.send "is_#{type}_repository?", source
params[:name] = name
params[:source_type] = type
params[:source_address] = source
r = Repository.new(params)
r.user = user
r.save!
r
end
end
protected
def detect_source_type
if GitRepository.is_git_repository?(source_address)
self.source_type = 'git'
elsif GitRepository.is_svn_repository?(source_address)
self.source_type = 'svn'
end
end
class SourceTypeValidator < ActiveModel::Validator
def validate(record)
if record.remote? && !record.source_type.present?
record.errors[:source_address] = "not a valid remote repository (types supported: #{SOURCE_TYPES.join(', ')})"
record.errors[:source_type] = "not present"
end
end
end
end