Commit 27bf7ae5 authored by ZJ van de Weg's avatar ZJ van de Weg Committed by Alfredo Sumaran

Refactor Gitlab::Gitignores

parent 74f8f260
......@@ -188,10 +188,8 @@ module BlobHelper
def gitignore_names
return @gitignore_names if defined?(@gitignore_names)
@gitignore_names = {
Global: Gitlab::Gitignore.global.map { |gitignore| { name: gitignore.name } },
# Note that the key here doesn't cover it really
Languages: Gitlab::Gitignore.languages_frameworks.map{ |gitignore| { name: gitignore.name } }
}
@gitignore_names = Gitlab::Template::Gitignore.categories.map do |k, _|
[k, Gitlab::Template::Gitignore.by_category(k)]
end.to_h
end
end
......@@ -33,7 +33,6 @@ module API
mount ::API::Commits
mount ::API::DeployKeys
mount ::API::Files
mount ::API::Gitignores
mount ::API::GroupMembers
mount ::API::Groups
mount ::API::Internal
......@@ -58,6 +57,7 @@ module API
mount ::API::Subscriptions
mount ::API::SystemHooks
mount ::API::Tags
mount ::API::Templates
mount ::API::Triggers
mount ::API::Users
mount ::API::Variables
......
......@@ -472,11 +472,11 @@ module API
expose :content
end
class GitignoresList < Grape::Entity
class TemplatesList < Grape::Entity
expose :name
end
class Gitignore < Grape::Entity
class Template < Grape::Entity
expose :name, :content
end
end
......
module API
class Gitignores < Grape::API
# Get the list of the available gitignore templates
#
# Example Request:
# GET /gitignores
get 'gitignores' do
present Gitlab::Gitignore.all, with: Entities::GitignoresList
end
# Get the text for a specific gitignore
#
# Parameters:
# name (required) - The name of a license
#
# Example Request:
# GET /gitignores/Elixir
#
get 'gitignores/:name' do
required_attributes! [:name]
gitignore = Gitlab::Gitignore.find(params[:name])
not_found!('.gitignore') unless gitignore
present gitignore, with: Entities::Gitignore
end
end
end
module API
class Templates < Grape::API
TEMPLATE_TYPES = {
gitignores: Gitlab::Template::Gitignore
}.freeze
TEMPLATE_TYPES.each do |template, klass|
# Get the list of the available template
#
# Example Request:
# GET /gitignores
# GET /gitlab_ci_ymls
get template.to_s do
present klass.all, with: Entities::TemplatesList
end
# Get the text for a specific template
#
# Parameters:
# name (required) - The name of a template
#
# Example Request:
# GET /gitignores/Elixir
# GET /gitlab_ci_ymls/Ruby
get "#{template}/:name" do
required_attributes! [:name]
new_template = klass.find(params[:name])
not_found!("#{template.to_s.singularize}") unless new_template
present new_template, with: Entities::Template
end
end
end
end
module Gitlab
class Gitignore
FILTER_REGEX = /\.gitignore\z/.freeze
def initialize(path)
@path = path
end
def name
File.basename(@path, '.gitignore')
end
def content
File.read(@path)
end
class << self
def all
languages_frameworks + global
end
def find(key)
file_name = "#{key}.gitignore"
directory = select_directory(file_name)
directory ? new(File.join(directory, file_name)) : nil
end
def global
files_for_folder(global_dir).map { |file| new(File.join(global_dir, file)) }
end
def languages_frameworks
files_for_folder(gitignore_dir).map { |file| new(File.join(gitignore_dir, file)) }
end
private
def select_directory(file_name)
[gitignore_dir, global_dir].find { |dir| File.exist?(File.join(dir, file_name)) }
end
def global_dir
File.join(gitignore_dir, 'Global')
end
def gitignore_dir
Rails.root.join('vendor/gitignore')
end
def files_for_folder(dir)
Dir.glob("#{dir.to_s}/*.gitignore").map { |file| file.gsub(FILTER_REGEX, '') }
end
end
end
end
module Gitlab
module Template
class BaseTemplate
def initialize(path)
@path = path
end
def name
File.basename(@path, self.class.extension)
end
def content
File.read(@path)
end
class << self
def all
self.category_directories.flat_map do |dir|
templates_for_folder(dir)
end
end
def find(key)
file_name = "#{key}#{self.extension}"
directory = select_directory(file_name)
directory ? new(File.join(directory, file_name)) : nil
end
def by_category(category)
templates_for_folder(categories[category])
end
def category_directories
self.categories.values.map { |subdir| File.join(base_dir, subdir)}
end
private
def select_directory(file_name)
category_directories.find { |dir| File.exist?(File.join(dir, file_name)) }
end
def templates_for_folder(dir)
Dir.glob("#{dir.to_s}/*#{self.extension}").select { |f| f =~ filter_regex }.map { |f| new(f) }
end
def filter_regex
/#{Regexp.escape(extension)}\z/
end
end
end
end
end
module Gitlab
module Template
class Gitignore < BaseTemplate
class << self
def extension
'.gitignore'
end
def categories
{
Languages: '',
Global: 'Global'
}
end
def base_dir
Rails.root.join('vendor/gitignore')
end
end
end
end
end
namespace :gitlab do
desc "GitLab | Update gitignore"
task :update_gitignore do
unless clone_gitignores
puts "Cloning the gitignores failed".color(:red)
return
end
remove_unneeded_files(gitignore_directory)
remove_unneeded_files(global_directory)
puts "Done".color(:green)
end
def clone_gitignores
FileUtils.rm_rf(gitignore_directory) if Dir.exist?(gitignore_directory)
FileUtils.cd vendor_directory
system('git clone --depth=1 --branch=master https://github.com/github/gitignore.git')
end
# Retain only certain files:
# - The LICENSE, because we have to
# - The sub dir global
# - The gitignores themself
# - Dir.entires returns also the entries '.' and '..'
def remove_unneeded_files(path)
Dir.foreach(path) do |file|
FileUtils.rm_rf(File.join(path, file)) unless file =~ /(\.{1,2}|LICENSE|Global|\.gitignore)\z/
end
end
private
def vendor_directory
Rails.root.join('vendor')
end
def gitignore_directory
File.join(vendor_directory, 'gitignore')
end
def global_directory
File.join(gitignore_directory, 'Global')
end
end
namespace :gitlab do
desc "GitLab | Update templates"
task :update_templates do
update("gitignore")
update("gitlab-ci-yml")
end
def update(directory)
unless clone_repository(directory)
puts "Cloning the #{directory} templates failed".red
return
end
remove_unneeded_files(directory)
puts "Done".green
end
def clone_repository(directory)
dir = File.join(vendor_directory, directory)
FileUtils.rm_rf(dir) if Dir.exist?(dir)
FileUtils.cd vendor_directory
system("git clone --depth=1 --branch=master #{TEMPLATE_DATA[directory]}")
end
# Retain only certain files:
# - The LICENSE, because we have to
# - The sub dir global
# - The gitignores themself
# - Dir.entires returns also the entries '.' and '..'
def remove_unneeded_files(directory)
regex = CLEANUP_REGEX[directory]
Dir.foreach(directory) do |file|
FileUtils.rm_rf(File.join(directory, file)) unless file =~ regex
end
end
private
TEMPLATE_DATA = {
"gitignore" => "https://github.com/github/gitignore.git",
"gitlab-ci-yml" => "https://gitlab.com/gitlab-org/gitlab-ci-yml.git"
}.freeze
CLEANUP_REGEX = {
"gitignore" => /(\.{1,2}|LICENSE|Global|\.gitignore)\z/,
"gitlab-ci-yml" => /(\.{1,2}|LICENSE|Pages|\.gitignore)\z/
}.freeze
def vendor_directory
Rails.root.join('vendor')
end
def gitignore_directory
File.join(vendor_directory, 'gitignore')
end
def gitlab_ci_directory
File.join(vendor_directory, 'gitlab-ci')
end
end
require 'spec_helper'
describe Gitlab::Gitignore do
subject { Gitlab::Gitignore }
describe Gitlab::Template::Gitignore do
subject { described_class }
describe '.all' do
it 'strips the gitignore suffix' do
......@@ -24,7 +24,7 @@ describe Gitlab::Gitignore do
it 'returns the Gitignore object of a valid file' do
ruby = subject.find('Ruby')
expect(ruby).to be_a Gitlab::Gitignore
expect(ruby).to be_a Gitlab::Template::Gitignore
expect(ruby.name).to eq('Ruby')
end
end
......
require 'spec_helper'
describe API::Gitignores, api: true do
describe API::Templates, api: true do
include ApiHelpers
describe 'Entity Gitignore' do
......
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