Commit 7ecebdd02df9b11fa6ba4f8033dcfe097935ed66

Authored by Dmitriy Zaporozhets
1 parent e2f946fd

Repository import during project creation often return timeout for medium and large repos.

So lets do it async. First create project, then import repo and create
satellite with Sidekiq
app/contexts/projects/create_context.rb
@@ -45,20 +45,6 @@ module Projects @@ -45,20 +45,6 @@ module Projects
45 45
46 @project.creator = current_user 46 @project.creator = current_user
47 47
48 - # Import project from cloneable resource  
49 - if @project.valid? && @project.import_url.present?  
50 - shell = Gitlab::Shell.new  
51 -  
52 - if shell.import_repository(@project.path_with_namespace, @project.import_url)  
53 - # We should create satellite for imported repo  
54 - @project.satellite.create unless @project.satellite.exists?  
55 - @project.imported = true  
56 - true  
57 - else  
58 - @project.errors.add(:import_url, 'cannot clone repo')  
59 - end  
60 - end  
61 -  
62 if @project.save 48 if @project.save
63 unless @project.group 49 unless @project.group
64 @project.users_projects.create(project_access: UsersProject::MASTER, user: current_user) 50 @project.users_projects.create(project_access: UsersProject::MASTER, user: current_user)
app/models/project.rb
@@ -37,8 +37,6 @@ class Project < ActiveRecord::Base @@ -37,8 +37,6 @@ class Project < ActiveRecord::Base
37 37
38 acts_as_taggable_on :labels, :issues_default_labels 38 acts_as_taggable_on :labels, :issues_default_labels
39 39
40 - attr_accessor :import_url  
41 -  
42 # Relations 40 # Relations
43 belongs_to :creator, foreign_key: "creator_id", class_name: "User" 41 belongs_to :creator, foreign_key: "creator_id", class_name: "User"
44 belongs_to :group, foreign_key: "namespace_id", conditions: "type = 'Group'" 42 belongs_to :group, foreign_key: "namespace_id", conditions: "type = 'Group'"
@@ -157,6 +155,10 @@ class Project < ActiveRecord::Base @@ -157,6 +155,10 @@ class Project < ActiveRecord::Base
157 import_url.present? 155 import_url.present?
158 end 156 end
159 157
  158 + def imported?
  159 + imported
  160 + end
  161 +
160 def check_limit 162 def check_limit
161 unless creator.can_create_project? 163 unless creator.can_create_project?
162 errors[:limit_reached] << ("Your own projects limit is #{creator.projects_limit}! Please contact administrator to increase it") 164 errors[:limit_reached] << ("Your own projects limit is #{creator.projects_limit}! Please contact administrator to increase it")
@@ -411,10 +413,6 @@ class Project &lt; ActiveRecord::Base @@ -411,10 +413,6 @@ class Project &lt; ActiveRecord::Base
411 !(forked_project_link.nil? || forked_project_link.forked_from_project.nil?) 413 !(forked_project_link.nil? || forked_project_link.forked_from_project.nil?)
412 end 414 end
413 415
414 - def imported?  
415 - imported  
416 - end  
417 -  
418 def personal? 416 def personal?
419 !group 417 !group
420 end 418 end
app/observers/project_observer.rb
1 class ProjectObserver < BaseObserver 1 class ProjectObserver < BaseObserver
2 def after_create(project) 2 def after_create(project)
3 - return true if project.forked? || project.imported?  
4 -  
5 - GitlabShellWorker.perform_async(  
6 - :add_repository,  
7 - project.path_with_namespace  
8 - )  
9 -  
10 - log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"") 3 + return true if project.forked?
  4 +
  5 + if project.import?
  6 + RepositoryImportWorker.perform_in(5.seconds, project.id)
  7 + else
  8 + GitlabShellWorker.perform_async(
  9 + :add_repository,
  10 + project.path_with_namespace
  11 + )
  12 +
  13 + log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"")
  14 + end
11 end 15 end
12 16
13 def after_update(project) 17 def after_update(project)
app/views/projects/empty.html.haml
1 = render 'clone_panel' 1 = render 'clone_panel'
2 2
3 -%div.git-empty  
4 - %fieldset  
5 - %legend Git global setup:  
6 - %pre.dark  
7 - :preserve  
8 - git config --global user.name "#{current_user.name}"  
9 - git config --global user.email "#{current_user.email}" 3 +- if @project.import? && !@project.imported
  4 + .save-project-loader
  5 + %center
  6 + = image_tag "ajax_loader.gif"
  7 + %h3 Importing repository.
  8 + %p.monospace git clone --bare #{@project.import_url}
  9 + %p Please wait until we import repository for you. Refresh at will.
10 10
11 - %fieldset  
12 - %legend Create Repository  
13 - %pre.dark  
14 - :preserve  
15 - mkdir #{@project.path}  
16 - cd #{@project.path}  
17 - git init  
18 - touch README  
19 - git add README  
20 - git commit -m 'first commit'  
21 - git remote add origin #{@project.url_to_repo}  
22 - git push -u origin master 11 +- else
  12 + %div.git-empty
  13 + %fieldset
  14 + %legend Git global setup:
  15 + %pre.dark
  16 + :preserve
  17 + git config --global user.name "#{current_user.name}"
  18 + git config --global user.email "#{current_user.email}"
23 19
24 - %fieldset  
25 - %legend Existing Git Repo?  
26 - %pre.dark  
27 - :preserve  
28 - cd existing_git_repo  
29 - git remote add origin #{@project.url_to_repo}  
30 - git push -u origin master 20 + %fieldset
  21 + %legend Create Repository
  22 + %pre.dark
  23 + :preserve
  24 + mkdir #{@project.path}
  25 + cd #{@project.path}
  26 + git init
  27 + touch README
  28 + git add README
  29 + git commit -m 'first commit'
  30 + git remote add origin #{@project.url_to_repo}
  31 + git push -u origin master
  32 +
  33 + %fieldset
  34 + %legend Existing Git Repo?
  35 + %pre.dark
  36 + :preserve
  37 + cd existing_git_repo
  38 + git remote add origin #{@project.url_to_repo}
  39 + git push -u origin master
31 40
32 - if can? current_user, :remove_project, @project 41 - if can? current_user, :remove_project, @project
33 .prepend-top-20 42 .prepend-top-20
app/workers/repository_import_worker.rb 0 → 100644
@@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
  1 +class RepositoryImportWorker
  2 + include Sidekiq::Worker
  3 + include Gitlab::ShellAdapter
  4 +
  5 + sidekiq_options queue: :gitlab_shell
  6 +
  7 + def perform(project_id)
  8 + project = Project.find(project_id)
  9 + result = gitlab_shell.send(:import_repository,
  10 + project.path_with_namespace,
  11 + project.import_url)
  12 +
  13 + if result
  14 + project.imported = true
  15 + project.save
  16 + project.satellite.create unless project.satellite.exists?
  17 + project.discover_default_branch
  18 + else
  19 + project.imported = false
  20 + end
  21 + end
  22 +end
db/migrate/20130812143708_add_import_url_to_project.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +class AddImportUrlToProject < ActiveRecord::Migration
  2 + def change
  3 + add_column :projects, :import_url, :string
  4 + end
  5 +end
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 # 11 #
12 # It's strongly recommended to check this file into your version control system. 12 # It's strongly recommended to check this file into your version control system.
13 13
14 -ActiveRecord::Schema.define(:version => 20130804151314) do 14 +ActiveRecord::Schema.define(:version => 20130812143708) do
15 15
16 create_table "deploy_keys_projects", :force => true do |t| 16 create_table "deploy_keys_projects", :force => true do |t|
17 t.integer "deploy_key_id", :null => false 17 t.integer "deploy_key_id", :null => false
@@ -178,6 +178,7 @@ ActiveRecord::Schema.define(:version =&gt; 20130804151314) do @@ -178,6 +178,7 @@ ActiveRecord::Schema.define(:version =&gt; 20130804151314) do
178 t.boolean "snippets_enabled", :default => true, :null => false 178 t.boolean "snippets_enabled", :default => true, :null => false
179 t.datetime "last_activity_at" 179 t.datetime "last_activity_at"
180 t.boolean "imported", :default => false, :null => false 180 t.boolean "imported", :default => false, :null => false
  181 + t.string "import_url"
181 end 182 end
182 183
183 add_index "projects", ["creator_id"], :name => "index_projects_on_owner_id" 184 add_index "projects", ["creator_id"], :name => "index_projects_on_owner_id"