diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb index bd850ac6..e5a168f6 100644 --- a/app/controllers/welcome_controller.rb +++ b/app/controllers/welcome_controller.rb @@ -31,6 +31,9 @@ class WelcomeController < ApplicationController DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z) def local_init + LocalSubject.delete_all + LocalStage.delete_all + LocalStageShixun.delete_all LocalShixun.delete_all LocalMirrorRepository.delete_all LocalShixunTagRepertoire.delete_all @@ -63,157 +66,117 @@ class WelcomeController < ApplicationController end end - def shixun_to_local - identifiers = params[:identifiers].split(",") - shixuns = Shixun.where(identifier: identifiers) - # 不重复导入 + def subject_to_local + subject_ids = params[:subject_ids].split(",") + subjects = Subject.where(id: subject_ids) ActiveRecord::Base.transaction do begin - shixuns.each do |shixun| - if LocalShixun.where(shixun_id: shixun.id).blank? - - local_shixun = LocalShixun.create!(name: shixun.name, description: shixun.description, user_id: User.current.id, status: 0, - trainee: shixun.trainee, webssh: shixun.webssh, multi_webssh: shixun.multi_webssh, - can_copy: shixun.can_copy, identifier: generate_identifier, shixun_id: shixun.id, - use_scope: shixun.use_scope, visits: 1, evaluate_script: shixun.evaluate_script, - local_giturl: shixun.git_url) - - # 同步镜像 - if shixun.mirror_repositories.present? - shixun.mirror_repositories.each do |mirror| - # 本地版的mirror id和线上的可能不一样,所以按名字取,然后再存 - # local_mirror = MirrorRepository.where(type_name: mirror.type_name).first.try(:id) - LocalMirrorRepository.create!(:local_shixun_id => local_shixun.id, :mirror_repository_id => mirror.id, type_name: mirror.type_name) - end - end - - # 同步技术标签 - shixun.shixun_tag_repertoires.each do |str| - LocalShixunTagRepertoire.create!(:tag_repertoire_id => str.tag_repertoire_id, :local_shixun_id => local_shixun.id) - end - - # 不需要同步版本库,版本库应该是从本地导入到线上的时候由线上版本创建的 - - # 同步复制关卡 - if shixun.challenges.present? - shixun.challenges.each do |challenge| - new_challenge = LocalChallenge.new - new_challenge.attributes = challenge.attributes.dup.except("id","shixun_id","user_id", "test_set_score") - new_challenge.local_shixun_id = local_shixun.id - new_challenge.save! - # 评测题,选择题暂时不考虑 - # 同步测试集 - if challenge.test_sets.present? - challenge.test_sets.each do |test_set| - new_test_set = LocalTestSet.new - new_test_set.attributes = test_set.attributes.dup.except("id","challenge_id") - new_test_set.local_challenge_id = new_challenge.id - new_test_set.save! - end - end - # 同步关卡标签 - challenge_tags = ChallengeTag.where("challenge_id =? and challenge_choose_id is null", challenge.id) - if challenge_tags.present? - challenge_tags.each do |challenge_tag| - LocalChallengeTag.create!(:local_challenge_id => new_challenge.id, :name => challenge_tag.try(:name)) + subjects.each do |subject| + if LocalSubject.where(subject_id: subject.id).blank? + + local_subject = LocalSubject.create!(name: subject.name, description: subject.description, status: 0, + learning_notes: subject.learning_notes, introduction: subject.introduction, + stages_count: subject.stages_count, stage_shixuns_count: subject.stage_shixuns_count, + subject_id: subject.id, shixuns_count: subject.shixuns_count) + + # 同步复制章节 + if subject.stages.present? + subject.stages.each do |stage| + new_stage = LocalStage.new + new_stage.attributes = stage.attributes.dup.except("id","user_id") + new_stage.local_subject_id = local_subject.id + new_stage.save! + + if stage.stage_shixuns.present? + stage.stage_shixuns.each do |stage_shixun| + new_stage_shixun = LocalStageShixun.new + new_stage_shixun.attributes = stage_shixun.attributes.dup.except("id") + new_stage_shixun.local_subject_id = local_subject.id + new_stage_shixun.local_subject_id = new_stage.id + new_stage_shixun.save! end end + + # 复制实训 + _shixun_to_local(stage.shixuns) end end end end render :json => {status: 0, message: "success"} + rescue Exception => e logger.error("shixun_local_in ##{e.message}") render :json => {status: -1, message: "error,#{e.message}"} raise ActiveRecord::Rollback end - end end - def local_to_shixun + def local_to_subject ActiveRecord::Base.transaction do - shixun_list = [] - LocalShixun.find_each do |local_shixun| - identifier = generate_identifier - shixun = Shixun.create!(name: local_shixun.name, description: local_shixun.description, user_id: User.current.id, - trainee: local_shixun.trainee, webssh: local_shixun.webssh, multi_webssh: local_shixun.multi_webssh, - can_copy: local_shixun.can_copy, identifier: identifier, reset_time: Time.now, - modify_time: Time.now, use_scope: local_shixun.use_scope, visits: 1, evaluate_script: local_shixun.evaluate_script) - m = ShixunMember.new(:user_id => User.current.id, :role => 1) - shixun.shixun_members << m - - # 同步镜像 - local_mirrors = LocalMirrorRepository.where(local_shixun_id: local_shixun.id) - if local_mirrors.present? - local_mirrors.each do |local_mirror| - local_mirror_new = MirrorRepository.where(type_name: local_mirror.try(:type_name)).first - ShixunMirrorRepository.create!(:shixun_id => shixun.id, :mirror_repository_id => local_mirror_new.id) - end - end - - # 同步技术标签 - local_shixun_tags = LocalShixunTagRepertoire.where(local_shixun_id: local_shixun.id) - if local_shixun_tags.present? - local_shixun_tags.each do |str| - ShixunTagRepertoire.create!(:tag_repertoire_id => str.tag_repertoire_id, :shixun_id => shixun.id) + subject_list = [] + LocalSubject.find_each do |local_subject| + subject = Subject.create!(name: local_subject.name, description: local_subject.description, user_id: User.current.id, + status: 0, learning_notes: local_subject.learning_notes, introduction: local_subject.introduction, + stages_count: local_subject.stages_count, stage_shixuns_count: local_subject.stage_shixuns_count, + shixuns_count: local_subject.shixuns_count, visits: 1) + m = SubjectMember.new(:user_id => User.current.id, :role => 1) + subject.subject_members << m + + # 同步章节信息 + local_stages = LocalStage.where(local_subject_id: local_subject.id) + if local_stages.present? + local_stages.each do |local_stage| + new_stage = Stage.new + new_stage.attributes = local_stage.attributes.dup.except("id","local_subject_id","subject_id") + new_stage.subject_id = subject.id + new_stage.save! + + # 同步章节实训关联表 + local_stage_shixuns = LocalStageShixun.where(local_stage_id: local_stage.id) + local_stage_shixuns.each do |local_stage_shixun| + # 先同步实训 + local_shixun = LocalShixun.where(id: local_stage_shixun.local_shixun_id).first + shixun = _local_to_shixun local_shixun if local_shixun.present? + + new_stage_shixun = StageShixun.new + new_stage_shixun.position = local_stage_shixun.position + new_stage_shixun.stage_id = new_stage.id + new_stage_shixun.subject_id = subject.id + new_stage_shixun.shixun_id = shixun.try(:id) + new_stage_shixun.save! + end end end + subject_list << subject.id + end + render :json => {status: 0, message: "success", identifier: subject_list} + end + end - # 创建版本库 - repository = Repository.new - repository.shixun = shixun - repository.type = 'Repository::Gitlab' - repository.identifier = shixun.identifier.downcase - repository.project_id = -1 - repository.save! - s = Trustie::Gitlab::Sync.new - s.create_shixun(shixun, repository) - raise "版本库创建失败" if shixun.gpid.blank? # 若和gitlab没同步成功,则抛出异常 - g = Gitlab.client - shixun.update_column(:git_url, g.project(shixun.gpid).path_with_namespace) - local_git_path = local_shixun.local_giturl.split('/').last if local_shixun.local_giturl.present? - new_giturl = "http://educoder:xinhu1ji2qu3@"+g.project(shixun.gpid).http_url_to_repo.split('//').last - # 如果有目录才执行 - if system("cd tmp/repositories/#{local_git_path}") - system("cd tmp/repositories/#{local_git_path};git remote remove origin;git remote add origin #{new_giturl}; - git add .;git commit -m '..';git push origin master") - end - - - # http://Hjqreturn:xinhu1ji2qu3@bdgit.educoder.net/Hjqreturn/pgfqe6ch8.git (fetch) - - # 同步关卡信息 - local_challenges = LocalChallenge.where(local_shixun_id: local_shixun.id) - if local_challenges.present? - local_challenges.each do |local_challenge| - new_challenge = Challenge.new - new_challenge.attributes = local_challenge.attributes.dup.except("id","local_shixun_id","user_id", "test_set_score") - new_challenge.user_id = User.current.id - new_challenge.shixun_id = shixun.id - new_challenge.save! + def shixun_to_local + identifiers = params[:identifiers].split(",") + shixuns = Shixun.where(identifier: identifiers) + # 不重复导入 + ActiveRecord::Base.transaction do + begin + _shixun_to_local(shixuns) + render :json => {status: 0, message: "success"} + rescue Exception => e + logger.error("shixun_local_in ##{e.message}") + render :json => {status: -1, message: "error,#{e.message}"} + raise ActiveRecord::Rollback + end - # 同步测试集 - local_test_sets = LocalTestSet.where(local_challenge_id: local_challenge.id) - if local_test_sets.present? - local_test_sets.each do |local_test_set| - new_test_set = TestSet.new - new_test_set.attributes = local_test_set.attributes.dup.except("id","challenge_id") - new_test_set.challenge_id = new_challenge.id - new_test_set.save! - end - end + end + end - # 同步关卡标签 - local_challenge_tags = LocalChallengeTag.where(local_challenge_id: local_challenge.id) - if local_challenge_tags.present? - local_challenge_tags.each do |local_challenge_tag| - ChallengeTag.create!(:challenge_id => new_challenge.id, :name => local_challenge_tag.try(:name)) - end - end - end - end + def local_to_shixun + ActiveRecord::Base.transaction do + shixun_list = [] + LocalShixun.find_each do |local_shixun| + shixun = _local_to_shixun local_shixun shixun_list << shixun.identifier end render :json => {status: 0, message: "success", identifier: shixun_list} @@ -519,6 +482,148 @@ class WelcomeController < ApplicationController end private + + def _shixun_to_local shixuns + shixuns.each do |shixun| + if LocalShixun.where(shixun_id: shixun.id).blank? + + local_shixun = LocalShixun.create!(name: shixun.name, description: shixun.description, user_id: User.current.id, status: 0, + trainee: shixun.trainee, webssh: shixun.webssh, multi_webssh: shixun.multi_webssh, + can_copy: shixun.can_copy, identifier: generate_identifier, shixun_id: shixun.id, + use_scope: shixun.use_scope, visits: 1, evaluate_script: shixun.evaluate_script, + local_giturl: shixun.git_url) + + # 同步更新实践课程中对应的shixun_id + LocalStageShixun.where(shixun_id: shixun.id).update_all(local_shixun_id: local_shixun.id) + + # 同步镜像 + if shixun.mirror_repositories.present? + shixun.mirror_repositories.each do |mirror| + # 本地版的mirror id和线上的可能不一样,所以按名字取,然后再存 + # local_mirror = MirrorRepository.where(type_name: mirror.type_name).first.try(:id) + LocalMirrorRepository.create!(:local_shixun_id => local_shixun.id, :mirror_repository_id => mirror.id, type_name: mirror.type_name) + end + end + + # 同步技术标签 + shixun.shixun_tag_repertoires.each do |str| + LocalShixunTagRepertoire.create!(:tag_repertoire_id => str.tag_repertoire_id, :local_shixun_id => local_shixun.id) + end + + # 不需要同步版本库,版本库应该是从本地导入到线上的时候由线上版本创建的 + + # 同步复制关卡 + if shixun.challenges.present? + shixun.challenges.each do |challenge| + new_challenge = LocalChallenge.new + new_challenge.attributes = challenge.attributes.dup.except("id","shixun_id","user_id", "test_set_score", "test_set_average", "exec_time", "praises_count") + new_challenge.local_shixun_id = local_shixun.id + new_challenge.save! + # 评测题,选择题暂时不考虑 + # 同步测试集 + if challenge.test_sets.present? + challenge.test_sets.each do |test_set| + new_test_set = LocalTestSet.new + new_test_set.attributes = test_set.attributes.dup.except("id","challenge_id","match_rule") + new_test_set.local_challenge_id = new_challenge.id + new_test_set.save! + end + end + # 同步关卡标签 + challenge_tags = ChallengeTag.where("challenge_id =? and challenge_choose_id is null", challenge.id) + if challenge_tags.present? + challenge_tags.each do |challenge_tag| + LocalChallengeTag.create!(:local_challenge_id => new_challenge.id, :name => challenge_tag.try(:name)) + end + end + end + end + end + end + end + + def _local_to_shixun local_shixun + identifier = generate_identifier + shixun = Shixun.create!(name: local_shixun.name, description: local_shixun.description, user_id: User.current.id, + trainee: local_shixun.trainee, webssh: local_shixun.webssh, multi_webssh: local_shixun.multi_webssh, + can_copy: local_shixun.can_copy, identifier: identifier, reset_time: Time.now, + modify_time: Time.now, use_scope: local_shixun.use_scope, visits: 1, evaluate_script: local_shixun.evaluate_script) + m = ShixunMember.new(:user_id => User.current.id, :role => 1) + shixun.shixun_members << m + + # 同步镜像 + local_mirrors = LocalMirrorRepository.where(local_shixun_id: local_shixun.id) + if local_mirrors.present? + local_mirrors.each do |local_mirror| + local_mirror_new = MirrorRepository.where(type_name: local_mirror.try(:type_name)).first + ShixunMirrorRepository.create!(:shixun_id => shixun.id, :mirror_repository_id => local_mirror_new.id) + end + end + + # 同步技术标签 + local_shixun_tags = LocalShixunTagRepertoire.where(local_shixun_id: local_shixun.id) + if local_shixun_tags.present? + local_shixun_tags.each do |str| + ShixunTagRepertoire.create!(:tag_repertoire_id => str.tag_repertoire_id, :shixun_id => shixun.id) + end + end + + # 创建版本库 + repository = Repository.new + repository.shixun = shixun + repository.type = 'Repository::Gitlab' + repository.identifier = shixun.identifier.downcase + repository.project_id = -1 + repository.save! + s = Trustie::Gitlab::Sync.new + s.create_shixun(shixun, repository) + raise "版本库创建失败" if shixun.gpid.blank? # 若和gitlab没同步成功,则抛出异常 + g = Gitlab.client + shixun.update_column(:git_url, g.project(shixun.gpid).path_with_namespace) + local_git_path = local_shixun.local_giturl.split('/').last if local_shixun.local_giturl.present? + new_giturl = "http://educoder:xinhu1ji2qu3@"+g.project(shixun.gpid).http_url_to_repo.split('//').last + # 如果有目录才执行 + if system("cd tmp/repositories/#{local_git_path}") + system("cd tmp/repositories/#{local_git_path};git remote remove origin;git remote add origin #{new_giturl}; + git add .;git commit -m '..';git push origin master") + end + + + # http://Hjqreturn:xinhu1ji2qu3@bdgit.educoder.net/Hjqreturn/pgfqe6ch8.git (fetch) + + # 同步关卡信息 + local_challenges = LocalChallenge.where(local_shixun_id: local_shixun.id) + if local_challenges.present? + local_challenges.each do |local_challenge| + new_challenge = Challenge.new + new_challenge.attributes = local_challenge.attributes.dup.except("id","local_shixun_id","user_id", "test_set_score") + new_challenge.user_id = User.current.id + new_challenge.shixun_id = shixun.id + new_challenge.save! + + # 同步测试集 + local_test_sets = LocalTestSet.where(local_challenge_id: local_challenge.id) + if local_test_sets.present? + local_test_sets.each do |local_test_set| + new_test_set = TestSet.new + new_test_set.attributes = local_test_set.attributes.dup.except("id","challenge_id") + new_test_set.challenge_id = new_challenge.id + new_test_set.save! + end + end + + # 同步关卡标签 + local_challenge_tags = LocalChallengeTag.where(local_challenge_id: local_challenge.id) + if local_challenge_tags.present? + local_challenge_tags.each do |local_challenge_tag| + ChallengeTag.create!(:challenge_id => new_challenge.id, :name => local_challenge_tag.try(:name)) + end + end + end + end + shixun + end + # 判断网站的入口,是课程 course 则跳过index去渲染 course 方法 def entry_select # url = request.original_url.gsub('/','') diff --git a/app/models/local_stage.rb b/app/models/local_stage.rb new file mode 100644 index 00000000..7cdabca4 --- /dev/null +++ b/app/models/local_stage.rb @@ -0,0 +1,3 @@ +class LocalStage < ActiveRecord::Base + # attr_accessible :description, :local_subject_id, :name, :position, :shixuns_count, :subject_id +end diff --git a/app/models/local_stage_shixun.rb b/app/models/local_stage_shixun.rb new file mode 100644 index 00000000..c2408b63 --- /dev/null +++ b/app/models/local_stage_shixun.rb @@ -0,0 +1,3 @@ +class LocalStageShixun < ActiveRecord::Base + # attr_accessible :local_subject_id, :position, :shixun_id, :stage_id, :subject_id +end diff --git a/app/models/local_subject.rb b/app/models/local_subject.rb new file mode 100644 index 00000000..83eb8522 --- /dev/null +++ b/app/models/local_subject.rb @@ -0,0 +1,3 @@ +class LocalSubject < ActiveRecord::Base + # attr_accessible :description, :introduction, :learning_notes, :name, :shixuns_count, :stage_shixuns_count, :stages_count, :status +end diff --git a/app/models/shixun.rb b/app/models/shixun.rb index 35193f2d..cef56af3 100644 --- a/app/models/shixun.rb +++ b/app/models/shixun.rb @@ -24,7 +24,7 @@ # 116:challenge创建关卡的时候返回结果错误 # class Shixun < ActiveRecord::Base - attr_accessible :description, :name, :changeset_num, :status, :user_id, :gpid, :language, :identifier, :authentication, :closer_id, :end_time, :publish_time, + attr_accessible :name, :changeset_num, :status, :user_id, :gpid, :language, :identifier, :authentication, :closer_id, :end_time, :publish_time, :propaedeutics, :trainee, :major_id, :homepage_show, :webssh, :hidden, :fork_from, :can_copy, :modify_time, :reset_time, :git_url, :use_scope, :vnc, :evaluate_script, :image_text, :exec_time, :test_set_permission, :hide_code, :excute_time, :forbid_copy @@ -54,6 +54,8 @@ class Shixun < ActiveRecord::Base has_many :shixun_tag_repertoires, :dependent => :destroy has_many :shixun_service_configs, :dependent => :destroy + has_one :shixun_info, dependent: :destroy + scope :visible, lambda{where(status: [2,3])} scope :min, lambda { select([:id, :name, :gpid, :modify_time, :reset_time, :language, :status, :identifier, :test_set_permission, :hide_code, :forbid_copy, :hidden, :webssh, :user_id, :code_hidden, @@ -66,6 +68,14 @@ class Shixun < ActiveRecord::Base #scope :visible, -> { where(status: -1) } after_create :send_tiding + def description + shixun_info.try(:description) + end + + def evaluate_script + shixun_info.try(:evaluate_script) + end + def should_compile? self.mirror_repositories.published_main_mirror.first.try(:should_compile) end diff --git a/app/models/shixun_info.rb b/app/models/shixun_info.rb new file mode 100644 index 00000000..45079557 --- /dev/null +++ b/app/models/shixun_info.rb @@ -0,0 +1,3 @@ +class ShixunInfo < ActiveRecord::Base + belongs_to :shixun +end diff --git a/config/routes.rb b/config/routes.rb index ad5a7bdc..ef6d561c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -301,6 +301,8 @@ RedmineApp::Application.routes.draw do ## oauth相关 get 'welcome/local_to_shixun' => 'welcome#local_to_shixun' get 'welcome/local_init' => 'welcome#local_init' get 'welcome/user_agents' => 'welcome#user_agents' + get 'welcome/subject_to_local' => 'welcome#subject_to_local' + get 'welcome/local_to_subject' => 'welcome#local_to_subject' # get 'competitions/home' => 'competitions#home' # get 'competitions/hn' => 'competitions#index' diff --git a/db/migrate/20190924070347_create_local_subjects.rb b/db/migrate/20190924070347_create_local_subjects.rb new file mode 100644 index 00000000..db8087d3 --- /dev/null +++ b/db/migrate/20190924070347_create_local_subjects.rb @@ -0,0 +1,17 @@ +class CreateLocalSubjects < ActiveRecord::Migration + def change + create_table :local_subjects do |t| + t.string :name + t.text :description + t.integer :status + t.text :learning_notes + t.string :introduction + t.integer :stages_count + t.integer :stage_shixuns_count + t.integer :shixuns_count + t.integer :subject_id + + t.timestamps + end + end +end diff --git a/db/migrate/20190924072232_create_local_stages.rb b/db/migrate/20190924072232_create_local_stages.rb new file mode 100644 index 00000000..309a30e1 --- /dev/null +++ b/db/migrate/20190924072232_create_local_stages.rb @@ -0,0 +1,14 @@ +class CreateLocalStages < ActiveRecord::Migration + def change + create_table :local_stages do |t| + t.integer :subject_id + t.string :name + t.text :description + t.integer :position + t.integer :shixuns_count + t.integer :local_subject_id + + t.timestamps + end + end +end diff --git a/db/migrate/20190924072622_create_local_stage_shixuns.rb b/db/migrate/20190924072622_create_local_stage_shixuns.rb new file mode 100644 index 00000000..93c1d5da --- /dev/null +++ b/db/migrate/20190924072622_create_local_stage_shixuns.rb @@ -0,0 +1,15 @@ +class CreateLocalStageShixuns < ActiveRecord::Migration + def change + create_table :local_stage_shixuns do |t| + t.integer :subject_id + t.integer :local_subject_id + t.integer :stage_id + t.integer :local_stage_id + t.integer :shixun_id + t.integer :local_shixun_id + t.integer :position + + t.timestamps + end + end +end