diff --git a/app/controllers/import/gitorious_controller.rb b/app/controllers/import/gitorious_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..627b4a171b82fa71b2a20aac6328dfb950f1b5bc --- /dev/null +++ b/app/controllers/import/gitorious_controller.rb @@ -0,0 +1,43 @@ +class Import::GitoriousController < Import::BaseController + + def new + redirect_to client.authorize_url(callback_import_gitorious_url) + end + + def callback + session[:gitorious_repos] = params[:repos] + redirect_to status_import_gitorious_url + end + + def status + @repos = client.repos + + @already_added_projects = current_user.created_projects.where(import_type: "gitorious") + already_added_projects_names = @already_added_projects.pluck(:import_source) + + @repos.to_a.reject! { |repo| already_added_projects_names.include? repo.full_name } + end + + def jobs + jobs = current_user.created_projects.where(import_type: "gitorious").to_json(only: [:id, :import_status]) + render json: jobs + end + + def create + @repo_id = params[:repo_id] + repo = client.repo(@repo_id) + @target_namespace = params[:new_namespace].presence || repo.namespace + @project_name = repo.name + + namespace = get_or_create_namespace || (render and return) + + @project = Gitlab::GitoriousImport::ProjectCreator.new(repo, namespace, current_user).execute + end + + private + + def client + @client ||= Gitlab::GitoriousImport::Client.new(session[:gitorious_repos]) + end + +end diff --git a/app/views/import/gitorious/status.html.haml b/app/views/import/gitorious/status.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..35ed0a717de3a3d7e8ea3373a693e431f7bdd05f --- /dev/null +++ b/app/views/import/gitorious/status.html.haml @@ -0,0 +1,41 @@ +%h3.page-title + %i.fa.fa-gitorious + Import repositories from Gitorious.org + +%p.light + Select projects you want to import. +%hr +%p + = button_tag 'Import all projects', class: "btn btn-success js-import-all" + +%table.table.import-jobs + %thead + %tr + %th From Gitorious + %th To GitLab + %th Status + %tbody + - @already_added_projects.each do |project| + %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"} + %td= project.import_source + %td + %strong= link_to project.path_with_namespace, project + %td.job-status + - if project.import_status == 'finished' + %span.cgreen + %i.fa.fa-check + done + - else + = project.human_import_status_name + + - @repos.each do |repo| + %tr{id: "repo_#{repo.id}"} + %td= repo.full_name + %td.import-target + = repo.full_name + %td.import-actions.job-status + = button_tag "Import", class: "btn js-add-to-import" + +:coffeescript + $ -> + new ImporterStatus("#{jobs_import_gitorious_path}", "#{import_gitorious_path}") diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 6f5851d61a1d70aa488763093f9c7efe6cec158e..33162ded4a6c363e5b1370ea434e34e212025925 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -66,6 +66,13 @@ Import projects from GitLab.com = render 'gitlab_import_modal' + .project-import.form-group + .col-sm-2 + .col-sm-10 + = link_to new_import_gitorious_path do + %i.fa.fa-heart + Import projects from Gitorious.org + %hr.prepend-botton-10 .form-group diff --git a/config/routes.rb b/config/routes.rb index 65786d8356664d05d27dafd845440613ca7a5426..101c5f3c3628e0ca008d63f1c26c58ffeec3dbf6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -67,6 +67,12 @@ Gitlab::Application.routes.draw do get :callback get :jobs end + + resource :gitorious, only: [:create, :new], controller: :gitorious do + get :status + get :callback + get :jobs + end end diff --git a/lib/gitlab/gitorious_import/client.rb b/lib/gitlab/gitorious_import/client.rb new file mode 100644 index 0000000000000000000000000000000000000000..5043f6a2ebd72ae661eddf710d25af438d698bf0 --- /dev/null +++ b/lib/gitlab/gitorious_import/client.rb @@ -0,0 +1,63 @@ +module Gitlab + module GitoriousImport + GITORIOUS_HOST = "https://gitorious.org" + + class Client + attr_reader :repo_list + + def initialize(repo_list) + @repo_list = repo_list + end + + def authorize_url(redirect_uri) + "#{GITORIOUS_HOST}/gitlab-import?callback_url=#{redirect_uri}" + end + + def repos + @repos ||= repo_names.map { |full_name| Repository.new(full_name) } + end + + def repo(id) + repos.find { |repo| repo.id == id } + end + + private + + def repo_names + repo_list.to_s.split(',').map(&:strip).reject(&:blank?) + end + end + + Repository = Struct.new(:full_name) do + def id + Digest::SHA1.hexdigest(full_name) + end + + def namespace + segments.first + end + + def path + segments.last + end + + def name + path.titleize + end + + def description + "" + end + + def import_url + "#{GITORIOUS_HOST}/#{full_name}.git" + end + + private + + def segments + full_name.split('/') + end + end + end +end diff --git a/lib/gitlab/gitorious_import/project_creator.rb b/lib/gitlab/gitorious_import/project_creator.rb new file mode 100644 index 0000000000000000000000000000000000000000..3cbebe53997414d96918713d80c52a6326e2012d --- /dev/null +++ b/lib/gitlab/gitorious_import/project_creator.rb @@ -0,0 +1,39 @@ +module Gitlab + module GitoriousImport + class ProjectCreator + attr_reader :repo, :namespace, :current_user + + def initialize(repo, namespace, current_user) + @repo = repo + @namespace = namespace + @current_user = current_user + end + + def execute + @project = Project.new( + name: repo.name, + path: repo.path, + description: repo.description, + namespace: namespace, + creator: current_user, + visibility_level: Gitlab::VisibilityLevel::PUBLIC, + import_type: "gitorious", + import_source: repo.full_name, + import_url: repo.import_url + ) + + if @project.save! + @project.reload + + if @project.import_failed? + @project.import_retry + else + @project.import_start + end + end + + @project + end + end + end +end diff --git a/spec/controllers/import/gitorious_controller_spec.rb b/spec/controllers/import/gitorious_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..07c9484bf1a2fafa2e98ccb64b0546dbcb5718d4 --- /dev/null +++ b/spec/controllers/import/gitorious_controller_spec.rb @@ -0,0 +1,67 @@ +require 'spec_helper' + +describe Import::GitoriousController do + let(:user) { create(:user) } + + before do + sign_in(user) + end + + describe "GET new" do + it "redirects to import endpoint on gitorious.org" do + get :new + + expect(controller).to redirect_to("https://gitorious.org/gitlab-import?callback_url=http://test.host/import/gitorious/callback") + end + end + + describe "GET callback" do + it "stores repo list in session" do + get :callback, repos: 'foo/bar,baz/qux' + + expect(session[:gitorious_repos]).to eq('foo/bar,baz/qux') + end + end + + describe "GET status" do + before do + @repo = OpenStruct.new(full_name: 'asd/vim') + end + + it "assigns variables" do + @project = create(:project, import_type: 'gitorious', creator_id: user.id) + controller.stub_chain(:client, :repos).and_return([@repo]) + + get :status + + expect(assigns(:already_added_projects)).to eq([@project]) + expect(assigns(:repos)).to eq([@repo]) + end + + it "does not show already added project" do + @project = create(:project, import_type: 'gitorious', creator_id: user.id, import_source: 'asd/vim') + controller.stub_chain(:client, :repos).and_return([@repo]) + + get :status + + expect(assigns(:already_added_projects)).to eq([@project]) + expect(assigns(:repos)).to eq([]) + end + end + + describe "POST create" do + before do + @repo = Gitlab::GitoriousImport::Repository.new('asd/vim') + end + + it "takes already existing namespace" do + namespace = create(:namespace, name: "asd", owner: user) + expect(Gitlab::GitoriousImport::ProjectCreator). + to receive(:new).with(@repo, namespace, user). + and_return(double(execute: true)) + controller.stub_chain(:client, :repo).and_return(@repo) + + post :create, format: :js + end + end +end diff --git a/spec/lib/gitlab/gitorious_import/project_creator.rb b/spec/lib/gitlab/gitorious_import/project_creator.rb new file mode 100644 index 0000000000000000000000000000000000000000..cf2318bb3a2e6764600e2679a18ad388de0ea686 --- /dev/null +++ b/spec/lib/gitlab/gitorious_import/project_creator.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe Gitlab::GitoriousImport::ProjectCreator do + let(:user) { create(:user) } + let(:repo) { Gitlab::GitoriousImport::Repository.new('foo/bar-baz-qux') } + let(:namespace){ create(:namespace) } + + it 'creates project' do + allow_any_instance_of(Project).to receive(:add_import_job) + + project_creator = Gitlab::GitoriousImport::ProjectCreator.new(repo, namespace, user) + project_creator.execute + project = Project.last + + expect(project.name).to eq("Bar Baz Qux") + expect(project.path).to eq("bar-baz-qux") + expect(project.namespace).to eq(namespace) + expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC) + expect(project.import_type).to eq("gitorious") + expect(project.import_source).to eq("foo/bar-baz-qux") + expect(project.import_url).to eq("https://gitorious.org/foo/bar-baz-qux.git") + end +end