Commit 06b614f9 authored by Rémy Coutable's avatar Rémy Coutable

Merge branch 'dm-gemfile-viewer'

See merge request !11346.
parents 4de3d0b1 1ede9957
...@@ -43,7 +43,19 @@ class Blob < SimpleDelegator ...@@ -43,7 +43,19 @@ class Blob < SimpleDelegator
BlobViewer::Readme, BlobViewer::Readme,
BlobViewer::License, BlobViewer::License,
BlobViewer::Contributing, BlobViewer::Contributing,
BlobViewer::Changelog BlobViewer::Changelog,
BlobViewer::Cartfile,
BlobViewer::ComposerJson,
BlobViewer::Gemfile,
BlobViewer::Gemspec,
BlobViewer::GodepsJson,
BlobViewer::PackageJson,
BlobViewer::Podfile,
BlobViewer::Podspec,
BlobViewer::PodspecJson,
BlobViewer::RequirementsTxt,
BlobViewer::YarnLock
].freeze ].freeze
attr_reader :project attr_reader :project
......
module BlobViewer
class Cartfile < DependencyManager
include Static
self.file_types = %i(cartfile)
def manager_name
'Carthage'
end
def manager_url
'https://github.com/Carthage/Carthage'
end
end
end
module BlobViewer
class ComposerJson < DependencyManager
include ServerSide
self.file_types = %i(composer_json)
def manager_name
'Composer'
end
def manager_url
'https://getcomposer.com/'
end
def package_name
@package_name ||= package_name_from_json('name')
end
def package_url
"https://packagist.org/packages/#{package_name}"
end
end
end
module BlobViewer
class DependencyManager < Base
include Auxiliary
self.partial_name = 'dependency_manager'
self.binary = false
def manager_name
raise NotImplementedError
end
def manager_url
raise NotImplementedError
end
def package_type
'package'
end
def package_name
nil
end
def package_url
nil
end
private
def package_name_from_json(key)
prepare!
JSON.parse(blob.data)[key] rescue nil
end
def package_name_from_method_call(name)
prepare!
match = blob.data.match(/#{name}\s*=\s*["'](?<name>[^"']+)["']/)
match[:name] if match
end
end
end
module BlobViewer
class Gemfile < DependencyManager
include Static
self.file_types = %i(gemfile gemfile_lock)
def manager_name
'Bundler'
end
def manager_url
'http://bundler.io/'
end
end
end
module BlobViewer
class Gemspec < DependencyManager
include ServerSide
self.file_types = %i(gemspec)
def manager_name
'RubyGems'
end
def manager_url
'https://rubygems.org/'
end
def package_type
'gem'
end
def package_name
@package_name ||= package_name_from_method_call('name')
end
def package_url
"https://rubygems.org/gems/#{package_name}"
end
end
end
module BlobViewer
class GodepsJson < DependencyManager
include Static
self.file_types = %i(godeps_json)
def manager_name
'godep'
end
def manager_url
'https://github.com/tools/godep'
end
end
end
module BlobViewer
class PackageJson < DependencyManager
include ServerSide
self.file_types = %i(package_json)
def manager_name
'npm'
end
def manager_url
'https://www.npmjs.com/'
end
def package_name
@package_name ||= package_name_from_json('name')
end
def package_url
"https://www.npmjs.com/package/#{package_name}"
end
end
end
module BlobViewer
class Podfile < DependencyManager
include Static
self.file_types = %i(podfile)
def manager_name
'CocoaPods'
end
def manager_url
'https://cocoapods.org/'
end
end
end
module BlobViewer
class Podspec < DependencyManager
include ServerSide
self.file_types = %i(podspec)
def manager_name
'CocoaPods'
end
def manager_url
'https://cocoapods.org/'
end
def package_type
'pod'
end
def package_name
@package_name ||= package_name_from_method_call('name')
end
def package_url
"https://cocoapods.org/pods/#{package_name}"
end
end
end
module BlobViewer
class PodspecJson < Podspec
self.file_types = %i(podspec_json)
def package_name
@package_name ||= package_name_from_json('name')
end
end
end
module BlobViewer
class RequirementsTxt < DependencyManager
include Static
self.file_types = %i(requirements_txt)
def manager_name
'pip'
end
def manager_url
'https://pip.pypa.io/'
end
end
end
module BlobViewer
class YarnLock < DependencyManager
include Static
self.file_types = %i(yarn_lock)
def manager_name
'Yarn'
end
def manager_url
'https://yarnpkg.com/'
end
end
end
= icon('cubes fw')
= succeed '.' do
This project manages its dependencies using
%strong= viewer.manager_name
- if viewer.package_name
and defines a #{viewer.package_type} named
%strong<
= link_to viewer.package_name, viewer.package_url, target: '_blank', rel: 'noopener noreferrer'
= link_to 'Learn more', viewer.manager_url, target: '_blank', rel: 'noopener noreferrer'
...@@ -5,4 +5,4 @@ This project is licensed under the ...@@ -5,4 +5,4 @@ This project is licensed under the
= succeed '.' do = succeed '.' do
%strong= license.name %strong= license.name
= link_to 'Learn more about this license', license.url, target: '_blank', rel: 'noopener noreferrer' = link_to 'Learn more', license.url, target: '_blank', rel: 'noopener noreferrer'
= icon('spinner spin fw') = icon('spinner spin fw')
Loading Analyzing file
...@@ -5,17 +5,33 @@ module Gitlab ...@@ -5,17 +5,33 @@ module Gitlab
# a README or a CONTRIBUTING file. # a README or a CONTRIBUTING file.
module FileDetector module FileDetector
PATTERNS = { PATTERNS = {
# Project files
readme: /\Areadme/i, readme: /\Areadme/i,
changelog: /\A(changelog|history|changes|news)/i, changelog: /\A(changelog|history|changes|news)/i,
license: /\A(licen[sc]e|copying)(\..+|\z)/i, license: /\A(licen[sc]e|copying)(\..+|\z)/i,
contributing: /\Acontributing/i, contributing: /\Acontributing/i,
version: 'version', version: 'version',
avatar: /\Alogo\.(png|jpg|gif)\z/,
# Configuration files
gitignore: '.gitignore', gitignore: '.gitignore',
koding: '.koding.yml', koding: '.koding.yml',
gemfile: /\A(Gemfile|gems\.rb)\z/,
gitlab_ci: '.gitlab-ci.yml', gitlab_ci: '.gitlab-ci.yml',
avatar: /\Alogo\.(png|jpg|gif)\z/, route_map: 'route-map.yml',
route_map: 'route-map.yml'
# Dependency files
cartfile: /\ACartfile/,
composer_json: 'composer.json',
gemfile: /\A(Gemfile|gems\.rb)\z/,
gemfile_lock: 'Gemfile.lock',
gemspec: /\.gemspec\z/,
godeps_json: 'Godeps.json',
package_json: 'package.json',
podfile: 'Podfile',
podspec_json: /\.podspec\.json\z/,
podspec: /\.podspec\z/,
requirements_txt: /requirements\.txt\z/,
yarn_lock: 'yarn.lock'
}.freeze }.freeze
# Returns an Array of file types based on the given paths. # Returns an Array of file types based on the given paths.
......
...@@ -423,7 +423,43 @@ feature 'File blob', :js, feature: true do ...@@ -423,7 +423,43 @@ feature 'File blob', :js, feature: true do
expect(page).to have_content('This project is licensed under the MIT License.') expect(page).to have_content('This project is licensed under the MIT License.')
# shows a learn more link # shows a learn more link
expect(page).to have_link('Learn more about this license', 'http://choosealicense.com/licenses/mit/') expect(page).to have_link('Learn more', 'http://choosealicense.com/licenses/mit/')
end
end
end
context '*.gemspec' do
before do
project.add_master(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add activerecord.gemspec",
file_path: 'activerecord.gemspec',
file_content: <<-SPEC.strip_heredoc
Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "activerecord"
end
SPEC
).execute
visit_blob('activerecord.gemspec')
end
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows names of dependency manager and package
expect(page).to have_content('This project manages its dependencies using RubyGems and defines a gem named activerecord.')
# shows a link to the gem
expect(page).to have_link('activerecord', 'https://rubygems.org/gems/activerecord')
# shows a learn more link
expect(page).to have_link('Learn more', 'http://choosealicense.com/licenses/mit/')
end end
end end
end end
......
require 'spec_helper'
describe BlobViewer::ComposerJson, model: true do
include FakeBlobHelpers
let(:project) { build(:project) }
let(:data) do
<<-SPEC.strip_heredoc
{
"name": "laravel/laravel",
"homepage": "https://laravel.com/"
}
SPEC
end
let(:blob) { fake_blob(path: 'composer.json', data: data) }
subject { described_class.new(blob) }
describe '#package_name' do
it 'returns the package name' do
expect(subject).to receive(:prepare!)
expect(subject.package_name).to eq('laravel/laravel')
end
end
end
require 'spec_helper'
describe BlobViewer::Gemspec, model: true do
include FakeBlobHelpers
let(:project) { build(:project) }
let(:data) do
<<-SPEC.strip_heredoc
Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "activerecord"
end
SPEC
end
let(:blob) { fake_blob(path: 'activerecord.gemspec', data: data) }
subject { described_class.new(blob) }
describe '#package_name' do
it 'returns the package name' do
expect(subject).to receive(:prepare!)
expect(subject.package_name).to eq('activerecord')
end
end
end
require 'spec_helper'
describe BlobViewer::PackageJson, model: true do
include FakeBlobHelpers
let(:project) { build(:project) }
let(:data) do
<<-SPEC.strip_heredoc
{
"name": "module-name",
"version": "10.3.1"
}
SPEC
end
let(:blob) { fake_blob(path: 'package.json', data: data) }
subject { described_class.new(blob) }
describe '#package_name' do
it 'returns the package name' do
expect(subject).to receive(:prepare!)
expect(subject.package_name).to eq('module-name')
end
end
end
require 'spec_helper'
describe BlobViewer::PodspecJson, model: true do
include FakeBlobHelpers
let(:project) { build(:project) }
let(:data) do
<<-SPEC.strip_heredoc
{
"name": "AFNetworking",
"version": "2.0.0"
}
SPEC
end
let(:blob) { fake_blob(path: 'AFNetworking.podspec.json', data: data) }
subject { described_class.new(blob) }
describe '#package_name' do
it 'returns the package name' do
expect(subject).to receive(:prepare!)
expect(subject.package_name).to eq('AFNetworking')
end
end
end
require 'spec_helper'
describe BlobViewer::Podspec, model: true do
include FakeBlobHelpers
let(:project) { build(:project) }
let(:data) do
<<-SPEC.strip_heredoc
Pod::Spec.new do |spec|
spec.name = 'Reachability'
spec.version = '3.1.0'
end
SPEC
end
let(:blob) { fake_blob(path: 'Reachability.podspec', data: data) }
subject { described_class.new(blob) }
describe '#package_name' do
it 'returns the package name' do
expect(subject).to receive(:prepare!)
expect(subject.package_name).to eq('Reachability')
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment