FogBugz project import

This commit is contained in:
Jared Szechy 2015-08-04 18:21:12 -04:00
parent 86556a079e
commit e156f42079
29 changed files with 889 additions and 16 deletions

View file

@ -47,6 +47,7 @@ v 7.14.1
- Only include base URL in OmniAuth full_host parameter (Stan Hu)
- Fix Error 500 in API when accessing a group that has an avatar (Stan Hu)
- Ability to enable SSL verification for Webhooks
- Add FogBugz project import (Jared Szechy)
v 7.14.0
- Fix bug where non-project members of the target project could set labels on new merge requests.

View file

@ -157,6 +157,9 @@ gem "slack-notifier", "~> 1.0.0"
# Asana integration
gem 'asana', '~> 0.0.6'
# FogBugz integration
gem 'ruby-fogbugz'
# d3
gem 'd3_rails', '~> 3.5.5'
@ -259,6 +262,7 @@ group :test do
gem 'email_spec', '~> 1.6.0'
gem 'webmock', '~> 1.21.0'
gem 'test_after_commit'
gem 'sham_rack'
end
group :production do

View file

@ -575,6 +575,8 @@ GEM
powerpack (~> 0.0.6)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.4)
ruby-fogbugz (0.1.1)
crack
ruby-progressbar (1.7.1)
ruby-saml (1.0.0)
nokogiri (>= 1.5.10)
@ -609,6 +611,8 @@ GEM
thor (~> 0.14)
settingslogic (2.0.9)
sexp_processor (4.4.5)
sham_rack (1.3.6)
rack
shoulda-matchers (2.8.0)
activesupport (>= 3.0.0)
sidekiq (3.3.0)
@ -845,12 +849,14 @@ DEPENDENCIES
rqrcode-rails3
rspec-rails (~> 3.3.0)
rubocop (= 0.28.0)
ruby-fogbugz
sanitize (~> 2.0)
sass-rails (~> 4.0.5)
sdoc
seed-fu
select2-rails (~> 3.5.9)
settingslogic
sham_rack
shoulda-matchers (~> 2.8.0)
sidekiq (~> 3.3)
sidetiq (= 0.6.3)

View file

@ -1,4 +1,5 @@
require 'gon'
require 'fogbugz'
class ApplicationController < ActionController::Base
include Gitlab::CurrentSettings
@ -20,7 +21,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?, :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?
rescue_from Encoding::CompatibilityError do |exception|
log_exception(exception)
@ -337,6 +338,10 @@ class ApplicationController < ActionController::Base
current_application_settings.import_sources.include?('google_code')
end
def fogbugz_import_enabled?
current_application_settings.import_sources.include?('fogbugz')
end
def git_import_enabled?
current_application_settings.import_sources.include?('git')
end

View file

@ -0,0 +1,106 @@
class Import::FogbugzController < Import::BaseController
before_action :verify_fogbugz_import_enabled
before_action :user_map, only: [:new_user_map, :create_user_map]
# Doesn't work yet due to bug in ruby-fogbugz, see below
rescue_from Fogbugz::AuthenticationException, with: :fogbugz_unauthorized
def new
end
def callback
begin
res = Gitlab::FogbugzImport::Client.new(import_params.symbolize_keys)
rescue
# Needed until https://github.com/firmafon/ruby-fogbugz/pull/9 is merged
return redirect_to :back, alert: 'Could not authenticate with FogBugz, check your URL, email, and password'
end
session[:fogbugz_token] = res.get_token
session[:fogbugz_uri] = params[:uri]
redirect_to new_user_map_import_fogbugz_path
end
def new_user_map
end
def create_user_map
user_map = params[:users]
unless user_map.is_a?(Hash) && user_map.all? { |k, v| !v[:name].blank? }
flash.now[:alert] = 'All users must have a name.'
render 'new_user_map' and return
end
session[:fogbugz_user_map] = user_map
flash[:notice] = 'The user map has been saved. Continue by selecting the projects you want to import.'
redirect_to status_import_fogbugz_path
end
def status
unless client.valid?
return redirect_to new_import_fogbugz_path
end
@repos = client.repos
@already_added_projects = current_user.created_projects.where(import_type: 'fogbugz')
already_added_projects_names = @already_added_projects.pluck(:import_source)
@repos.reject! { |repo| already_added_projects_names.include? repo.name }
end
def jobs
jobs = current_user.created_projects.where(import_type: 'fogbugz').to_json(only: [:id, :import_status])
render json: jobs
end
def create
@repo_id = params[:repo_id]
repo = client.repo(@repo_id)
fb_session = { uri: session[:fogbugz_uri], token: session[:fogbugz_token] }
@target_namespace = current_user.namespace
@project_name = repo.name
namespace = @target_namespace
umap = session[:fogbugz_user_map] || client.user_map
@project = Gitlab::FogbugzImport::ProjectCreator.new(repo, fb_session, namespace, current_user, umap).execute
end
private
def client
@client ||= Gitlab::FogbugzImport::Client.new(token: session[:fogbugz_token], uri: session[:fogbugz_uri])
end
def user_map
@user_map ||= begin
user_map = client.user_map
stored_user_map = session[:fogbugz_user_map]
user_map.update(stored_user_map) if stored_user_map
user_map
end
end
def fogbugz_unauthorized(exception)
flash[:alert] = exception.message
redirect_to new_import_fogbugz_path
end
def import_params
params.permit(:uri, :email, :password)
end
def verify_fogbugz_import_enabled
not_found! unless fogbugz_import_enabled?
end
end

View file

@ -83,7 +83,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','git']
import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git']
)
end

View file

@ -43,6 +43,8 @@ class Project < ActiveRecord::Base
extend Gitlab::ConfigHelper
extend Enumerize
UNKNOWN_IMPORT_URL = 'http://unknown.git'
default_value_for :archived, false
default_value_for :visibility_level, gitlab_config_features.visibility_level
default_value_for :issues_enabled, gitlab_config_features.issues

View file

@ -0,0 +1,43 @@
module Projects
class DownloadService < BaseService
WHITELIST = [
/^[^.]+\.fogbugz.com$/
]
def initialize(project, url)
@project, @url = project, url
end
def execute
return nil unless valid_url?(@url)
uploader = FileUploader.new(@project)
uploader.download!(@url)
uploader.store!
filename = uploader.image? ? uploader.file.basename : uploader.file.filename
{
'alt' => filename,
'url' => uploader.secure_url,
'is_image' => uploader.image?
}
end
private
def valid_url?(url)
url && http?(url) && valid_domain?(url)
end
def http?(url)
url =~ /\A#{URI::regexp(['http', 'https'])}\z/
end
def valid_domain?(url)
host = URI.parse(url).host
WHITELIST.any? { |entry| entry === host }
end
end
end

View file

@ -0,0 +1,25 @@
- page_title "FogBugz Import"
%h3.page-title
%i.fa.fa-bug
Import projects from FogBugz
%hr
= form_tag callback_import_fogbugz_path, class: 'form-horizontal' do
%p
To get started you enter your FogBugz URL and login information below.
In the next steps, you'll be able to map users and select the projects
you want to import.
.form-group
= label_tag :uri, 'FogBugz URL', class: 'control-label'
.col-sm-4
= text_field_tag :uri, nil, placeholder: 'https://mycompany.fogbugz.com', class: 'form-control'
.form-group
= label_tag :email, 'FogBugz Email', class: 'control-label'
.col-sm-4
= text_field_tag :email, nil, class: 'form-control'
.form-group
= label_tag :password, 'FogBugz Password', class: 'control-label'
.col-sm-4
= password_field_tag :password, nil, class: 'form-control'
.form-actions
= submit_tag 'Continue to the next step', class: 'btn btn-create'

View file

@ -0,0 +1,49 @@
- page_title 'User map', 'FogBugz import'
%h3.page-title
%i.fa.fa-bug
Import projects from FogBugz
%hr
= form_tag create_user_map_import_fogbugz_path, class: 'form-horizontal' do
%p
Customize how FogBugz email addresses and usernames are imported into GitLab.
In the next step, you'll be able to select the projects you want to import.
%p
The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames wil be imported into GitLab. You can change this by populating the table below.
%ul
%li
%strong Default: Map a FogBugz account ID to a full name
%p
An empty GitLab User field will add the FogBugz user's full name
(e.g. "By John Smith") in the description of all issues and comments.
It will also associate and/or assign these issues and comments with
the project creator.
%li
%strong Map a FogBugz account ID to a GitLab user
%p
Selecting a GitLab user will add a link to the GitLab user in the descriptions
of issues and comments (e.g. "By <a href="#">@johnsmith</a>"). It will also
associate and/or assign these issues and comments with the selected user.
%table.table
%thead
%tr
%th ID
%th Name
%th Email
%th GitLab User
%tbody
- @user_map.each do |id, user|
%tr
%td= id
%td= text_field_tag "users[#{id}][name]", user[:name], class: 'form-control'
%td= text_field_tag "users[#{id}][email]", user[:email], class: 'form-control'
%td
= users_select_tag("users[#{id}][gitlab_user]", class: 'custom-form-control',
scope: :all, email_user: true, selected: user[:gitlab_user])
.form-actions
= submit_tag 'Continue to the next step', class: 'btn btn-create'
:coffeescript
new UsersSelect()

View file

@ -0,0 +1,51 @@
- page_title "FogBugz import"
%h3.page-title
%i.fa.fa-bug
Import projects from FogBugz
- if @repos.any?
%p.light
Select projects you want to import.
%p.light
Optionally, you can
= link_to 'customize', new_user_map_import_fogbugz_path
how FogBugz email addresses and usernames are imported into GitLab.
%hr
%p
= button_tag 'Import all projects', class: 'btn btn-success js-import-all'
%table.table.import-jobs
%thead
%tr
%th From FogBugz
%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.namespace.becomes(Namespace), project]
%td.job-status
- if project.import_status == 'finished'
%span
%i.fa.fa-check
done
- elsif project.import_status == 'started'
%i.fa.fa-spinner.fa-spin
started
- else
= project.human_import_status_name
- @repos.each do |repo|
%tr{id: "repo_#{repo.id}"}
%td
= repo.name
%td.import-target
= "#{current_user.username}/#{repo.name}"
%td.import-actions.job-status
= button_tag "Import", class: "btn js-add-to-import"
:coffeescript
new ImporterStatus("#{jobs_import_fogbugz_path}", "#{import_fogbugz_path}")

View file

@ -72,6 +72,11 @@
%i.fa.fa-google
Google Code
- if fogbugz_import_enabled?
= link_to new_import_fogbugz_path, class: 'btn import_fogbugz' do
%i.fa.fa-bug
Fogbugz
- if git_import_enabled?
= link_to "#", class: 'btn js-toggle-button import_git' do
%i.fa.fa-git

View file

@ -7,19 +7,28 @@ class RepositoryImportWorker
def perform(project_id)
project = Project.find(project_id)
unless project.import_url == Project::UNKNOWN_IMPORT_URL
import_result = gitlab_shell.send(:import_repository,
project.path_with_namespace,
project.import_url)
return project.import_fail unless import_result
else
unless project.create_repository
return project.import_fail
end
end
data_import_result = if project.import_type == 'github'
data_import_result = case project.import_type
when 'github'
Gitlab::GithubImport::Importer.new(project).execute
elsif project.import_type == 'gitlab'
when 'gitlab'
Gitlab::GitlabImport::Importer.new(project).execute
elsif project.import_type == 'bitbucket'
when 'bitbucket'
Gitlab::BitbucketImport::Importer.new(project).execute
elsif project.import_type == 'google_code'
when 'google_code'
Gitlab::GoogleCodeImport::Importer.new(project).execute
when 'fogbugz'
Gitlab::FogbugzImport::Importer.new(project).execute
else
true
end

View file

@ -158,7 +158,7 @@ Settings.gitlab.default_projects_features['snippets'] = false if Settings.
Settings.gitlab.default_projects_features['visibility_level'] = Settings.send(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE)
Settings.gitlab['repository_downloads_path'] = File.absolute_path(Settings.gitlab['repository_downloads_path'] || 'tmp/repositories', Rails.root)
Settings.gitlab['restricted_signup_domains'] ||= []
Settings.gitlab['import_sources'] ||= ['github','bitbucket','gitlab','gitorious','google_code','git']
Settings.gitlab['import_sources'] ||= ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git']
#
# Reply by email

View file

@ -99,6 +99,15 @@ Gitlab::Application.routes.draw do
get :new_user_map, path: :user_map
post :create_user_map, path: :user_map
end
resource :fogbugz, only: [:create, :new], controller: :fogbugz do
get :status
post :callback
get :jobs
get :new_user_map, path: :user_map
post :create_user_map, path: :user_map
end
end
#

View file

@ -3,6 +3,7 @@
1. [Bitbucket](import_projects_from_bitbucket.md)
2. [GitHub](import_projects_from_github.md)
3. [GitLab.com](import_projects_from_gitlab_com.md)
4. [FogBugz](import_projects_from_fogbugz.md)
4. [SVN](migrating_from_svn.md)
### Note

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

View file

@ -0,0 +1,29 @@
# Import your project from FogBugz to GitLab
It only takes a few simple steps to import your project from FogBugz.
The importer will import all of your cases and comments with original case
numbers and timestamps. You will also have the opportunity to map FogBugz
users to GitLab users.
* From your GitLab dashboard click 'New project'
* Click on the 'FogBugz' button
![FogBugz](fogbugz_importer/fogbugz_import_select_fogbogz.png)
* Enter your FogBugz URL, email address, and password.
![Login](fogbugz_importer/fogbugz_import_login.png)
* Create mapping from FogBugz users to GitLab users.
![User Map](fogbugz_importer/fogbugz_import_user_map.png)
* Select the projects you wish to import by clicking the Import buttons
![Import Project](fogbugz_importer/fogbugz_import_select_project.png)
* Once the import has finished click the link to take you to the project
dashboard. Follow the directions to push your existing repository.
![Finished](fogbugz_importer/fogbugz_import_finished.png)

View file

@ -0,0 +1,56 @@
require 'fogbugz'
module Gitlab
module FogbugzImport
class Client
attr_reader :api
def initialize(options = {})
if options[:uri] && options[:token]
@api = ::Fogbugz::Interface.new(options)
elsif options[:uri] && options[:email] && options[:password]
@api = ::Fogbugz::Interface.new(options)
@api.authenticate
@api
end
end
def get_token
@api.token
end
def valid?
!get_token.blank?
end
def user_map
users = {}
res = @api.command(:listPeople)
res['people']['person'].each do |user|
users[user['ixPerson']] = { name: user['sFullName'], email: user['sEmail'] }
end
users
end
def repos
res = @api.command(:listProjects)
@repos ||= res['projects']['project'].map { |proj| FogbugzImport::Repository.new(proj) }
end
def repo(id)
repos.find { |r| r.id.to_s == id.to_s }
end
def cases(project_id)
project_name = repo(project_id).name
res = @api.command(:search, q: "project:'#{project_name}'", cols: 'ixPersonAssignedTo,ixPersonOpenedBy,ixPersonClosedBy,sStatus,sPriority,sCategory,fOpen,sTitle,sLatestTextSummary,dtOpened,dtClosed,dtResolved,dtLastUpdated,events')
return [] unless res['cases']['count'].to_i > 0
res['cases']['case']
end
def categories
@api.command(:listCategories)
end
end
end
end

View file

@ -0,0 +1,298 @@
module Gitlab
module FogbugzImport
class Importer
attr_reader :project, :repo
def initialize(project)
@project = project
import_data = project.import_data.try(:data)
repo_data = import_data['repo'] if import_data
@repo = FogbugzImport::Repository.new(repo_data)
@known_labels = Set.new
end
def execute
return true unless repo.valid?
data = project.import_data.try(:data)
client = Gitlab::FogbugzImport::Client.new(token: data['fb_session']['token'], uri: data['fb_session']['uri'])
@cases = client.cases(@repo.id.to_i)
@categories = client.categories
import_cases
true
end
private
def user_map
@user_map ||= begin
user_map = Hash.new
import_data = project.import_data.try(:data)
stored_user_map = import_data['user_map'] if import_data
user_map.update(stored_user_map) if stored_user_map
user_map
end
end
def import_labels
@categories['categories']['category'].each do |label|
create_label(label['sCategory'])
@known_labels << name
end
end
def nice_label_color(name)
case name
when 'Blocker'
'#ff0000'
when 'Crash'
'#ffcfcf'
when 'Major'
'#deffcf'
when 'Minor'
'#cfe9ff'
when 'Bug'
'#d9534f'
when 'Feature'
'#44ad8e'
when 'Technical Task'
'#4b6dd0'
else
'#e2e2e2'
end
end
def create_label(name)
color = nice_label_color(name)
Label.create!(project_id: project.id, title: name, color: color)
end
def user_info(person_id)
user_hash = user_map[person_id.to_s]
user_name = ''
gitlab_id = nil
unless user_hash.nil?
user_name = user_hash['name']
if user = User.find_by(id: user_hash['gitlab_user'])
user_name = "@#{user.username}"
gitlab_id = user.id
end
end
{ name: user_name, gitlab_id: gitlab_id }
end
def import_cases
return unless @cases
while bug = @cases.shift
author = user_info(bug['ixPersonOpenedBy'])[:name]
date = DateTime.parse(bug['dtOpened'])
comments = bug['events']['event']
content = format_content(opened_content(comments))
body = format_issue_body(author, date, content)
labels = []
[bug['sCategory'], bug['sPriority']].each do |label|
unless label.blank?
labels << label
unless @known_labels.include?(label)
create_label(label)
@known_labels << label
end
end
end
assignee_id = user_info(bug['ixPersonAssignedTo'])[:gitlab_id]
author_id = user_info(bug['ixPersonOpenedBy'])[:gitlab_id] || project.creator_id
issue = Issue.create!(
project_id: project.id,
title: bug['sTitle'],
description: body,
author_id: author_id,
assignee_id: assignee_id,
state: bug['fOpen'] == 'true' ? 'opened' : 'closed'
)
issue.add_labels_by_names(labels)
if issue.iid != bug['ixBug']
issue.update_attribute(:iid, bug['ixBug'])
end
import_issue_comments(issue, comments)
issue.update_attribute(:created_at, date)
last_update = DateTime.parse(bug['dtLastUpdated'])
issue.update_attribute(:updated_at, last_update)
end
end
def opened_content(comments)
while comment = comments.shift
if comment['sVerb'] == 'Opened'
return comment['s']
end
end
''
end
def import_issue_comments(issue, comments)
Note.transaction do
while comment = comments.shift
verb = comment['sVerb']
next if verb == 'Opened' || verb === 'Closed'
content = format_content(comment['s'])
attachments = format_attachments(comment['rgAttachments'])
updates = format_updates(comment)
next if content.blank? && attachments.empty? && updates.empty?
author = user_info(comment['ixPerson'])[:name]
author_id = user_info(comment['ixPerson'])[:gitlab_id] || project.creator_id
date = DateTime.parse(comment['dt'])
body = format_issue_comment_body(
comment['ixBugEvent'],
author,
date,
content,
attachments,
updates
)
note = Note.create!(
project_id: project.id,
noteable_type: "Issue",
noteable_id: issue.id,
author_id: author_id,
note: body
)
note.update_attribute(:created_at, date)
note.update_attribute(:updated_at, date)
end
end
end
def linkify_issues(s)
s = s.gsub(/([Ii]ssue) ([0-9]+)/, '\1 #\2')
s = s.gsub(/([Cc]ase) ([0-9]+)/, '\1 #\2')
s
end
def escape_for_markdown(s)
s = s.gsub(/^#/, "\\#")
s = s.gsub(/^-/, "\\-")
s = s.gsub("`", "\\~")
s = s.gsub("\r", "")
s = s.gsub("\n", " \n")
s
end
def format_content(raw_content)
return raw_content if raw_content.nil?
linkify_issues(escape_for_markdown(raw_content))
end
def format_attachments(raw_attachments)
return [] unless raw_attachments
attachments = case raw_attachments['attachment']
when Array
raw_attachments['attachment']
when Hash
[raw_attachments['attachment']]
else
[]
end
attachments.map! { |a| format_attachment(a) }
attachments.compact
end
def format_attachment(attachment)
link = build_attachment_url(attachment['sURL'])
res = ::Projects::DownloadService.new(project, link).execute
return nil if res.nil?
text = "[#{res['alt']}](#{res['url']})"
text = "!#{text}" if res['is_image']
text
end
def build_attachment_url(rel_url)
data = project.import_data.try(:data)
uri = data['fb_session']['uri']
token = data['fb_session']['token']
"#{uri}/#{rel_url}&token=#{token}"
end
def format_updates(comment)
updates = []
if comment['sChanges']
updates << "*Changes: #{linkify_issues(comment['sChanges'].chomp)}*"
end
if comment['evtDescription']
updates << "*#{comment['evtDescription']}*"
end
updates
end
def format_issue_body(author, date, content)
body = []
body << "*By #{author} on #{date} (imported from FogBugz)*"
body << '---'
if content.blank?
content = '*(No description has been entered for this issue)*'
end
body << content
body.join("\n\n")
end
def format_issue_comment_body(id, author, date, content, attachments, updates)
body = []
body << "*By #{author} on #{date} (imported from FogBugz)*"
body << '---'
if content.blank?
content = "*(No comment has been entered for this change)*"
end
body << content
if updates.any?
body << '---'
body += updates
end
if attachments.any?
body << '---'
body += attachments
end
body.join("\n\n")
end
end
end
end

View file

@ -0,0 +1,38 @@
module Gitlab
module FogbugzImport
class ProjectCreator
attr_reader :repo, :fb_session, :namespace, :current_user, :user_map
def initialize(repo, fb_session, namespace, current_user, user_map = nil)
@repo = repo
@fb_session = fb_session
@namespace = namespace
@current_user = current_user
@user_map = user_map
end
def execute
project = ::Projects::CreateService.new(current_user,
name: repo.safe_name,
path: repo.path,
namespace: namespace,
creator: current_user,
visibility_level: Gitlab::VisibilityLevel::INTERNAL,
import_type: 'fogbugz',
import_source: repo.name,
import_url: Project::UNKNOWN_IMPORT_URL
).execute
import_data = project.create_import_data(
data: {
'repo' => repo.raw_data,
'user_map' => user_map,
'fb_session' => fb_session
}
)
project
end
end
end
end

View file

@ -0,0 +1,31 @@
module Gitlab
module FogbugzImport
class Repository
attr_accessor :raw_data
def initialize(raw_data)
@raw_data = raw_data
end
def valid?
raw_data.is_a?(Hash)
end
def id
raw_data['ixProject']
end
def name
raw_data['sProject']
end
def safe_name
name.gsub(/[^\s\w.-]/, '')
end
def path
safe_name.gsub(/[\s]/, '_')
end
end
end
end

View file

@ -19,6 +19,7 @@ module Gitlab
'GitLab.com' => 'gitlab',
'Gitorious.org' => 'gitorious',
'Google Code' => 'google_code',
'FogBugz' => 'fogbugz',
'Any repo by URL' => 'git',
}
end

View file

@ -0,0 +1,39 @@
require 'spec_helper'
require_relative 'import_spec_helper'
describe Import::FogbugzController do
include ImportSpecHelper
let(:user) { create(:user) }
before do
sign_in(user)
end
describe 'GET status' do
before do
@repo = OpenStruct.new(name: 'vim')
stub_client(valid?: true)
end
it 'assigns variables' do
@project = create(:project, import_type: 'fogbugz', creator_id: user.id)
stub_client(repos: [@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: 'fogbugz', creator_id: user.id, import_source: 'vim')
stub_client(repos: [@repo])
get :status
expect(assigns(:already_added_projects)).to eq([@project])
expect(assigns(:repos)).to eq([])
end
end
end

View file

@ -0,0 +1,65 @@
require 'spec_helper'
describe Projects::DownloadService do
describe 'File service' do
before do
@user = create :user
@project = create :project, creator_id: @user.id, namespace: @user.namespace
end
context 'for a URL that is not on whitelist' do
before do
url = 'https://code.jquery.com/jquery-2.1.4.min.js'
@link_to_file = download_file(@project, url)
end
it { expect(@link_to_file).to eq(nil) }
end
context 'for URLs that are on the whitelist' do
before do
sham_rack_app = ShamRack.at('mycompany.fogbugz.com').stub
sham_rack_app.register_resource('/rails_sample.jpg', File.read(Rails.root + 'spec/fixtures/rails_sample.jpg'), 'image/jpg')
sham_rack_app.register_resource('/doc_sample.txt', File.read(Rails.root + 'spec/fixtures/doc_sample.txt'), 'text/plain')
end
after do
ShamRack.unmount_all
end
context 'an image file' do
before do
url = 'http://mycompany.fogbugz.com/rails_sample.jpg'
@link_to_file = download_file(@project, url)
end
it { expect(@link_to_file).to have_key('alt') }
it { expect(@link_to_file).to have_key('url') }
it { expect(@link_to_file).to have_key('is_image') }
it { expect(@link_to_file['is_image']).to be true }
it { expect(@link_to_file['url']).to match("/#{@project.path_with_namespace}") }
it { expect(@link_to_file['url']).to match('rails_sample.jpg') }
it { expect(@link_to_file['alt']).to eq('rails_sample') }
end
context 'a txt file' do
before do
url = 'http://mycompany.fogbugz.com/doc_sample.txt'
@link_to_file = download_file(@project, url)
end
it { expect(@link_to_file).to have_key('alt') }
it { expect(@link_to_file).to have_key('url') }
it { expect(@link_to_file).to have_key('is_image') }
it { expect(@link_to_file['is_image']).to be false }
it { expect(@link_to_file['url']).to match("/#{@project.path_with_namespace}") }
it { expect(@link_to_file['url']).to match('doc_sample.txt') }
it { expect(@link_to_file['alt']).to eq('doc_sample.txt') }
end
end
end
def download_file(repository, url)
Projects::DownloadService.new(repository, url).execute
end
end