diff options
-rw-r--r-- | CHANGELOG | 2 | ||||
-rw-r--r-- | Gemfile | 2 | ||||
-rw-r--r-- | app/controllers/application_controller.rb | 6 | ||||
-rw-r--r-- | app/controllers/import/gitlab_projects_controller.rb | 42 | ||||
-rw-r--r-- | app/controllers/projects_controller.rb | 25 | ||||
-rw-r--r-- | app/models/application_setting.rb | 2 | ||||
-rw-r--r-- | app/models/todo.rb | 4 | ||||
-rw-r--r-- | app/views/import/gitlab_projects/new.html.haml | 20 | ||||
-rw-r--r-- | app/views/import/gitlab_projects/status.html.haml | 0 | ||||
-rw-r--r-- | app/views/projects/new.html.haml | 22 | ||||
-rw-r--r-- | config/routes.rb | 2 | ||||
-rw-r--r-- | features/dashboard/new_project.feature | 2 | ||||
-rw-r--r-- | features/steps/dashboard/new_project.rb | 5 | ||||
-rw-r--r-- | lib/gitlab/current_settings.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/import_export/import_service.rb | 12 | ||||
-rw-r--r-- | lib/gitlab/import_sources.rb | 3 | ||||
-rw-r--r-- | spec/features/projects/import_export/import_file_spec.rb | 48 | ||||
-rw-r--r-- | spec/features/projects/import_export/test_project_export.tar.gz | bin | 0 -> 672360 bytes |
18 files changed, 189 insertions, 10 deletions
diff --git a/CHANGELOG b/CHANGELOG index 364690286e1..e7f38c93be9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -176,6 +176,8 @@ v 8.8.0 - API support for the 'since' and 'until' operators on commit requests (Paco Guzman) - Fix Gravatar hint in user profile when Gravatar is disabled. !3988 (Artem Sidorenko) - Expire repository exists? and has_visible_content? caches after a push if necessary + - Fix unintentional filtering bug in issues sorted by milestone due (Takuya Noguchi) + - GitLab project import and export functionality - Fix unintentional filtering bug in Issue/MR sorted by milestone due (Takuya Noguchi) - Fix adding a todo for private group members (Ahmad Sherif) - Bump ace-rails-ap gem version from 2.0.1 to 4.0.2 which upgrades Ace Editor from 1.1.2 to 1.2.3 @@ -218,7 +218,7 @@ gem 'jquery-turbolinks', '~> 2.1.0' gem 'addressable', '~> 2.3.8' gem 'bootstrap-sass', '~> 3.3.0' -gem 'font-awesome-rails', '~> 4.2' +gem 'font-awesome-rails', '~> 4.6.1' gem 'gitlab_emoji', '~> 0.3.0' gem 'gon', '~> 6.0.1' gem 'jquery-atwho-rails', '~> 1.3.2' diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index cd6ae507cf1..726acbdb3ed 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -24,7 +24,7 @@ class ApplicationController < ActionController::Base protect_from_forgery with: :exception helper_method :abilities, :can?, :current_application_settings - helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled? + helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled?, :gitlab_project_import_enabled? rescue_from Encoding::CompatibilityError do |exception| log_exception(exception) @@ -326,6 +326,10 @@ class ApplicationController < ActionController::Base current_application_settings.import_sources.include?('git') end + def gitlab_project_import_enabled? + current_application_settings.import_sources.include?('gitlab_project') + end + def two_factor_authentication_required? current_application_settings.require_two_factor_authentication end diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb new file mode 100644 index 00000000000..a4ac55cd2a4 --- /dev/null +++ b/app/controllers/import/gitlab_projects_controller.rb @@ -0,0 +1,42 @@ +class Import::GitlabProjectsController < Import::BaseController + before_action :verify_gitlab_project_import_enabled + before_action :verify_project_and_namespace_access + + rescue_from OAuth::Error, with: :gitlab_project_unauthorized + + def new + @namespace_id = project_params[:namespace_id] + @path = project_params[:path] + end + + def create + @project = Project.create_from_import_job(current_user_id: current_user.id, + tmp_file: File.expand_path(params[:file].path), + namespace_id: project_params[:namespace_id], + project_path: project_params[:path]) + + redirect_to dashboard_projects_path + end + + private + + def verify_project_and_namespace_access + unless namespace_access? + render_403 + end + end + + def namespace_access? + current_user.can?(:create_projects, Namespace.find(project_params[:namespace_id])) + end + + def verify_gitlab_project_import_enabled + render_404 unless gitlab_project_import_enabled? + end + + def project_params + params.permit( + :path, :namespace_id, + ) + end +end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index a6479c42d94..5c657290046 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -7,7 +7,7 @@ class ProjectsController < Projects::ApplicationController before_action :assign_ref_vars, :tree, only: [:show], if: :repo_exists? # Authorize - before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping] + before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping, :download_export, :export] before_action :event_filter, only: [:show, :activity] layout :determine_layout @@ -185,6 +185,23 @@ class ProjectsController < Projects::ApplicationController ) end + def export + @project.add_export_job(current_user_id: current_user.id) + + redirect_to( + edit_project_path(@project), + notice: "Project export successfully started" + ) + end + + def download_export + if export_project_path + send_file export_project_path, disposition: 'attachment' + else + render_404 + end + end + def toggle_star current_user.toggle_star(@project) @project.reload @@ -247,4 +264,10 @@ class ProjectsController < Projects::ApplicationController def get_id project.repository.root_ref end + + def export_project_path + # TODO: move this, probably to ImportExport and refactor + folder = File.join(Settings.shared['path'], 'tmp/project_exports', @project.path_with_namespace) + Dir.glob("#{folder}/*export.tar.gz").max_by {|f| File.ctime(f)} + end end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index a744f937918..b2fb54ba5e7 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -123,7 +123,7 @@ class ApplicationSetting < ActiveRecord::Base default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'], default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'], restricted_signup_domains: Settings.gitlab['restricted_signup_domains'], - import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git'], + import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git', 'gitlab_project'], shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'], max_artifacts_size: Settings.artifacts['max_size'], require_two_factor_authentication: false, diff --git a/app/models/todo.rb b/app/models/todo.rb index 3a091373329..b0401463269 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -45,6 +45,10 @@ class Todo < ActiveRecord::Base target_type == "Commit" end + def for_project? + target_type == "Project" + end + # override to return commits, which are not active record def target if for_commit? diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml new file mode 100644 index 00000000000..d93ae42c1bf --- /dev/null +++ b/app/views/import/gitlab_projects/new.html.haml @@ -0,0 +1,20 @@ +- page_title "GitLab Import" +- header_title "Projects", root_path +%h3.page-title + %i.fa.fa-gitlab + Import projects from GitLab +%hr + += form_tag import_gitlab_project_path, class: 'form-horizontal', multipart: true do + %p + To get started add your exported project file below: + .form-group + = hidden_field_tag :namespace_id, @namespace_id + = hidden_field_tag :path, @path + = label_tag :file, class: 'control-label' do + %span GitLab project export + .col-sm-10 + = file_field_tag :file, class: '' + + .form-actions + = submit_tag 'Continue to the next step', class: 'btn btn-create' diff --git a/app/views/import/gitlab_projects/status.html.haml b/app/views/import/gitlab_projects/status.html.haml new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/app/views/import/gitlab_projects/status.html.haml diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index f9ac16b32f3..79ef9284268 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -88,7 +88,12 @@ - if git_import_enabled? = link_to "#", class: 'btn js-toggle-button import_git' do %i.fa.fa-git - %span Any repo by URL + %span Repo by URL + + - if gitlab_project_import_enabled? + = link_to new_import_gitlab_project_path, class: 'btn import_gitlab_project project-submit' do + %i.fa.fa-gitlab + %span GitLab project .js-toggle-content.hide = render "shared/import_form", f: f @@ -122,3 +127,18 @@ $('.modal-header .close').bind('click', function() { $(".modal").hide(); }); + $('.import_gitlab_project').bind('click', function() { + var _href = $("a.import_gitlab_project").attr("href"); + $(".import_gitlab_project").attr("href", _href + '?namespace_id=' + $("#project_namespace_id").val() + '&path=' + $("#project_path").val()); + }); + $('.import_gitlab_project').attr('disabled',true) + $('.import_gitlab_project').attr('title', 'Project path required.'); + $('#project_path').keyup(function(){ + if($(this).val().length !=0) { + $('.import_gitlab_project').attr('disabled', false); + $('.import_gitlab_project').attr('title',''); + } else { + $('.import_gitlab_project').attr('disabled',true); + $('.import_gitlab_project').attr('title', 'Project path required.'); + } + }) diff --git a/config/routes.rb b/config/routes.rb index e2492fbab46..bc1112de0f5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -454,6 +454,8 @@ Rails.application.routes.draw do post :housekeeping post :toggle_star post :markdown_preview + post :export + post :download_export get :autocomplete_sources get :activity end diff --git a/features/dashboard/new_project.feature b/features/dashboard/new_project.feature index 76392068357..56b4a639c01 100644 --- a/features/dashboard/new_project.feature +++ b/features/dashboard/new_project.feature @@ -14,7 +14,7 @@ Background: @javascript Scenario: I should see instructions on how to import from Git URL Given I see "New Project" page - When I click on "Any repo by URL" + When I click on "Repo by URL" Then I see instructions on how to import from Git URL @javascript diff --git a/features/steps/dashboard/new_project.rb b/features/steps/dashboard/new_project.rb index a0aad66184d..ad20201c2c5 100644 --- a/features/steps/dashboard/new_project.rb +++ b/features/steps/dashboard/new_project.rb @@ -19,7 +19,8 @@ class Spinach::Features::NewProject < Spinach::FeatureSteps expect(page).to have_link('GitLab.com') expect(page).to have_link('Gitorious.org') expect(page).to have_link('Google Code') - expect(page).to have_link('Any repo by URL') + expect(page).to have_link('Repo by URL') + expect(page).to have_link('GitLab project') end step 'I click on "Import project from GitHub"' do @@ -36,7 +37,7 @@ class Spinach::Features::NewProject < Spinach::FeatureSteps end end - step 'I click on "Any repo by URL"' do + step 'I click on "Repo by URL"' do first('.import_git').click end diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb index 5e7532f57ae..38c0f1aba47 100644 --- a/lib/gitlab/current_settings.rb +++ b/lib/gitlab/current_settings.rb @@ -36,7 +36,7 @@ module Gitlab default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'], default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'], restricted_signup_domains: Settings.gitlab['restricted_signup_domains'], - import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git'], + import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git', 'gitlab_project'], shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'], max_artifacts_size: Settings.artifacts['max_size'], require_two_factor_authentication: false, diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index db71f72efec..95d4fb17ead 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -64,6 +64,18 @@ module Gitlab def wiki_repo_path File.join(@shared.export_path, 'project.wiki.bundle') end + + def attributes_for_todo + { user_id: @current_user.id, + project_id: project_tree.project.id, + target_type: 'Project', + target: project_tree.project, + action: Todo::IMPORTED, + author_id: @current_user.id, + state: :pending, + target_id: project_tree.project.id + } + end end end end diff --git a/lib/gitlab/import_sources.rb b/lib/gitlab/import_sources.rb index ccfdfbe73e8..4cae819d356 100644 --- a/lib/gitlab/import_sources.rb +++ b/lib/gitlab/import_sources.rb @@ -20,7 +20,8 @@ module Gitlab 'Gitorious.org' => 'gitorious', 'Google Code' => 'google_code', 'FogBugz' => 'fogbugz', - 'Any repo by URL' => 'git', + 'Repo by URL' => 'git', + 'GitLab project' => 'gitlab_project' } end diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb new file mode 100644 index 00000000000..03298149b60 --- /dev/null +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -0,0 +1,48 @@ +require 'spec_helper' + +feature 'project import', feature: true, js: true do + include Select2Helper + + let(:user) { create(:admin) } + let!(:namespace) { create(:namespace, name: "asd", owner: user) } + let(:file) { File.join(Rails.root, 'spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') } + let(:export_path) { "#{Dir::tmpdir}/import_file_spec" } + let(:project) { Project.last } + + background do + allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) + login_as(user) + end + + after(:each) do + FileUtils.rm_rf(export_path, secure: true) + end + + scenario 'user imports an exported project successfully' do + expect(Project.all.count).to be_zero + + visit new_project_path + + select2('2', from: '#project_namespace_id') + fill_in :project_path, with:'test-project-path', visible: true + click_link 'GitLab project' + + expect(page).to have_content('GitLab project export') + expect(URI.parse(current_url).query).to eq('namespace_id=2&path=test-project-path') + + attach_file('file', file) + + click_on 'Continue to the next step' # import starts + + expect(project).not_to be_nil + expect(project.issues).not_to be_empty + expect(project.merge_requests).not_to be_empty + expect(project.repo_exists?).to be true + expect(wiki_exists?).to be true + end + + def wiki_exists? + wiki = ProjectWiki.new(project) + File.exists?(wiki.repository.path_to_repo) && !wiki.repository.empty? + end +end diff --git a/spec/features/projects/import_export/test_project_export.tar.gz b/spec/features/projects/import_export/test_project_export.tar.gz Binary files differnew file mode 100644 index 00000000000..b85055070d8 --- /dev/null +++ b/spec/features/projects/import_export/test_project_export.tar.gz |