redmine_with_git 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 41c5cef1997a8a62157c3688bfac26cfd32716f6c42a5b746e69ce1a905804ce
4
+ data.tar.gz: 691b298324491169f88ce6701d550a513a8082542e3891d5c2fb8c4d51836f00
5
+ SHA512:
6
+ metadata.gz: ddae741acd3582e0961e70d0d96aa3be9644f9cf5c6d9e0e798264d32f4afc6b1c99e4db5a4eb96e95cce57591ce8fec95b06abd04c2e5057d02a3f35bc7c62a
7
+ data.tar.gz: f7e6693264bc94c099d629a22534dfe9b193a5f20971aba95af4eda4b9d94303a3d61cf69c3a06b01210dfa7d4b43fe80ad5dcb878258baded852a420450de5f
@@ -0,0 +1,48 @@
1
+ class RedmineWithGitController < ApplicationController
2
+ before_filter :require_admin
3
+
4
+ accept_api_auth :export, :import
5
+
6
+ helper ::RedmineWithGitHelper
7
+
8
+ def index
9
+ @load = ::RedmineWithGit::Tableless::Load.new
10
+ end
11
+
12
+ def export
13
+ Tempfile.open('redmine_export') do |file|
14
+ ::RedmineWithGit::Dump::All.new(file.path, true)
15
+ send_file(file.path, filename: export_file_name, type: 'application/x-tar',
16
+ size: file.size)
17
+ end
18
+ end
19
+
20
+ def import
21
+ @load = ::RedmineWithGit::Tableless::Load.new(import_params)
22
+ @load.save
23
+ respond_to do |format|
24
+ format.html { import_respond_to_html }
25
+ format.api { render_validation_errors(@load) }
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def import_respond_to_html
32
+ if @load.errors.empty?
33
+ redirect_to redmine_with_git_path, notice: 'Backup imported'
34
+ else
35
+ render :index
36
+ end
37
+ end
38
+
39
+ def export_file_name
40
+ "redmine-backup_#{Time.zone.now.strftime('%Y-%m-%d_%H-%M-%S')}.tar"
41
+ end
42
+
43
+ def import_params
44
+ ps = params[::RedmineWithGit::Tableless::Load.model_name.param_key]
45
+ return {} unless ps.present?
46
+ ps.permit(:path)
47
+ end
48
+ end
@@ -0,0 +1,24 @@
1
+ module RedmineWithGitHelper
2
+ def export_api_curl_command
3
+ curl_command("curl -JLO '#{export_redmine_with_git_url(key: User.current.api_key)}'")
4
+ end
5
+
6
+ def import_api_curl_command
7
+ curl_command(<<IMPORT_CURL)
8
+ curl -X POST \\
9
+ -F '#{import_param_key}=@<PATH_TO_BACKUP_FILE>' \\
10
+ -F 'key=#{User.current.api_key}' \\
11
+ #{import_redmine_with_git_url(format: 'json')}
12
+ IMPORT_CURL
13
+ end
14
+
15
+ private
16
+
17
+ def curl_command(command)
18
+ content_tag(:pre, command)
19
+ end
20
+
21
+ def import_param_key
22
+ "#{::RedmineWithGit::Tableless::Load.model_name.param_key}[path]"
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ module RedmineWithGit
2
+ module Tableless
3
+ class Load < ::EacRailsUtils::TablelessModel
4
+ attribute :path, String
5
+
6
+ validates :path, presence: true
7
+
8
+ def save
9
+ return false unless valid?
10
+ ::RedmineWithGit::Load::All.new(path.path)
11
+ true
12
+ rescue StandardError => ex
13
+ errors.add(:path, ex.message)
14
+ false
15
+ end
16
+
17
+ def path_path
18
+ path.is_a?(Pathname) ? path.path : path.to_s
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,10 @@
1
+ <div>
2
+ <%= link_to_function(l(:button_show), "$('#redmine_with_git_api').toggle();")%>
3
+ <div id='redmine_with_git_api' class="autoscroll" >
4
+ <h4>Export CURL command</h4>
5
+ <%= export_api_curl_command %>
6
+ <h4>Import CURL command</h4>
7
+ <%= import_api_curl_command %>
8
+ </div>
9
+ </div>
10
+ <%= javascript_tag("$('#redmine_with_git_api').hide();") %>
@@ -0,0 +1 @@
1
+ <%= link_to 'Export', export_redmine_with_git_path %>
@@ -0,0 +1,9 @@
1
+ <%= labelled_form_for @load, url: import_redmine_with_git_path, method: :post do |f| %>
2
+ <%= error_messages_for @load %>
3
+ <div class="box tabular">
4
+ <p>
5
+ <%= f.file_field :path %>
6
+ </p>
7
+ </div>
8
+ <%= submit_tag('Import') %>
9
+ <% end %>
@@ -0,0 +1,9 @@
1
+ <h2>Redmine With Git</h2>
2
+ <h3>Export</h3>
3
+ <%= render partial: 'export' %>
4
+ <h3>Import</h3>
5
+ <%= render partial: 'import' %>
6
+ <% if Setting.rest_api_enabled? %>
7
+ <h3>API</h3>
8
+ <%= render partial: 'api' %>
9
+ <% end %>
@@ -0,0 +1,9 @@
1
+ Redmine::Plugin.post_register :redmine_with_git do
2
+ # Source: https://github.com/esquilo-azul/redmine_plugins_helper
3
+ requires_redmine_plugin(:redmine_plugins_helper, version_or_higher: '0.4.0')
4
+ # Source: https://github.com/jbox-web/redmine_bootstrap_kit.git
5
+ # Note: redmine_bootstrap_kit is a redmine_git_hosting's dependency.
6
+ requires_redmine_plugin(:redmine_bootstrap_kit, version_or_higher: '0.2.5')
7
+ # Source: https://github.com/jbox-web/redmine_git_hosting.git
8
+ requires_redmine_plugin(:redmine_git_hosting, version_or_higher: '1.2.3')
9
+ end
@@ -0,0 +1,2 @@
1
+ en:
2
+ field_path: Path
@@ -0,0 +1,2 @@
1
+ pt-BR:
2
+ field_path: Caminho
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ RedmineApp::Application.routes.draw do
2
+ get '/redmine_with_git', to: 'redmine_with_git#index', as: 'redmine_with_git'
3
+ get '/redmine_with_git/export', to: 'redmine_with_git#export', as: 'export_redmine_with_git'
4
+ post '/redmine_with_git/import', to: 'redmine_with_git#import', as: 'import_redmine_with_git'
5
+ end
data/init.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'redmine'
2
+ require 'redmine_with_git/version'
3
+
4
+ require 'eac_rails_utils'
5
+ require 'eac_ruby_utils'
6
+
7
+ Redmine::Plugin.register :redmine_with_git do
8
+ name 'RedmineWithGit'
9
+ author 'Esquilo Azul Company'
10
+ description 'Utilities for Redmine + plugin redmine_git_hosting.'
11
+ version ::RedmineWithGit::VERSION
12
+ url 'https://github.com/esquilo-azul/redmine_with_git'
13
+ author_url 'https://github.com/esquilo-azul'
14
+
15
+ Redmine::MenuManager.map :admin_menu do |menu|
16
+ menu.push :redmine_with_git, { controller: 'redmine_with_git', action: 'index', id: nil },
17
+ caption: 'Redmine with Git',
18
+ if: proc { User.current.admin? }
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ module RedmineWithGit
2
+ module Dump
3
+ class All < ::RedmineWithGit::Dump::Base
4
+ include ::RedmineWithGit::DumpLoad::All
5
+
6
+ private
7
+
8
+ def run_command
9
+ on_temp_dir do
10
+ RESOURCES.each { |a| build_sub(a) }
11
+ super
12
+ end
13
+ end
14
+
15
+ def build_sub(a)
16
+ resource_class(a).new(resource_file_path(a), overwrite)
17
+ end
18
+
19
+ def build_command
20
+ create_tar_command(tmpdir, false)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,52 @@
1
+ module RedmineWithGit
2
+ module Dump
3
+ class Base < ::RedmineWithGit::DumpLoad::Base
4
+ def initialize(path, overwrite)
5
+ @overwrite = overwrite
6
+ super(path)
7
+ end
8
+
9
+ private
10
+
11
+ attr_reader :overwrite
12
+
13
+ def run
14
+ start_banner
15
+ if ::File.exist?(path) && !overwrite
16
+ Rails.logger.warn "File \"#{path}\" already exists"
17
+ return
18
+ end
19
+ run_command
20
+ validate_exported
21
+ end_banner
22
+ end
23
+
24
+ def start_banner
25
+ Rails.logger.info "Dumping resource \"#{resource_name}\" to \"#{path}\"..."
26
+ end
27
+
28
+ def end_banner
29
+ Rails.logger.info("#{path}: #{number_to_human_size(::File.size(path))}, #{path_type}")
30
+ end
31
+
32
+ def run_command
33
+ build_command.execute!(output_file: path)
34
+ end
35
+
36
+ def create_tar_command(dir, compression = true)
37
+ tar = "cd #{Shellwords.escape(dir)}; tar -c *"
38
+ tar << " | #{compress_args.join(' ')}" if compression
39
+ env.command(['bash', '-c', tar])
40
+ end
41
+
42
+ def compress_args
43
+ %w(gzip -9 -c -)
44
+ end
45
+
46
+ def validate_exported
47
+ raise "File \"#{path}\" was not generated" unless ::File.exist?(path)
48
+ raise "File \"#{path}\" has zero size" unless ::File.size(path) > 0
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,17 @@
1
+ module RedmineWithGit
2
+ module Dump
3
+ class Database < ::RedmineWithGit::Dump::Base
4
+ include ::RedmineWithGit::DumpLoad::Database
5
+
6
+ private
7
+
8
+ def build_command
9
+ env.command(
10
+ [password_arg, 'pg_dump', '-x', '-c', '-O',
11
+ '-h', database_schema['host'], '-U', database_schema['username'], '-d',
12
+ database_schema['database'], '@ESC_|'] + compress_args
13
+ )
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ module RedmineWithGit
2
+ module Dump
3
+ class Files < ::RedmineWithGit::Dump::Base
4
+ include ::RedmineWithGit::DumpLoad::Files
5
+
6
+ private
7
+
8
+ def build_command
9
+ create_tar_command(files_path)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module RedmineWithGit
2
+ module Dump
3
+ class Git < ::RedmineWithGit::Dump::Base
4
+ include ::RedmineWithGit::DumpLoad::Git
5
+
6
+ private
7
+
8
+ def build_command
9
+ create_tar_command(repositories_path).prepend(sudo_command)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,34 @@
1
+ module RedmineWithGit
2
+ module DumpLoad
3
+ module All
4
+ DATABASE = 'database.gz'.freeze
5
+ FILES = 'files.tar.gz'.freeze
6
+ GIT = 'git.tar.gz'.freeze
7
+
8
+ RESOURCES = %w(database files git).freeze
9
+
10
+ private
11
+
12
+ attr_reader :tmpdir
13
+
14
+ def on_temp_dir
15
+ ::Dir.mktmpdir do |dir|
16
+ @tmpdir = dir
17
+ yield
18
+ end
19
+ end
20
+
21
+ def resource_class(resource_name)
22
+ "#{self.class.name.deconstantize}::#{resource_name.camelize}".constantize
23
+ end
24
+
25
+ def resource_file_name(resource_name)
26
+ self.class.const_get(resource_name.underscore.upcase)
27
+ end
28
+
29
+ def resource_file_path(resource_name)
30
+ File.join(tmpdir, resource_file_name(resource_name))
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ module RedmineWithGit
2
+ module DumpLoad
3
+ class Base
4
+ include ::ActionView::Helpers::NumberHelper
5
+
6
+ def initialize(path)
7
+ @path = path
8
+ run
9
+ end
10
+
11
+ private
12
+
13
+ attr_reader :path
14
+
15
+ def resource_name
16
+ self.class.name.demodulize.underscore
17
+ end
18
+
19
+ def env
20
+ ::EacRubyUtils::Envs.local
21
+ end
22
+
23
+ def path_type
24
+ env.command('file', '-b', path).execute!
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ module RedmineWithGit
2
+ module DumpLoad
3
+ module Database
4
+ def database_schema
5
+ Rails.configuration.database_configuration[Rails.env]
6
+ end
7
+
8
+ def password_arg
9
+ '@ESC_PGPASSWORD=' + Shellwords.escape(database_schema['password'])
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module RedmineWithGit
2
+ module DumpLoad
3
+ module Files
4
+ private
5
+
6
+ def files_path
7
+ Rails.root.join('files').realpath.to_s
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module RedmineWithGit
2
+ module DumpLoad
3
+ module Git
4
+ private
5
+
6
+ def repositories_path
7
+ ::RedmineGitHosting::Config.gitolite_global_storage_dir
8
+ end
9
+
10
+ def sudo_command
11
+ ::RedmineGitHosting::Commands.send(:sudo)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ module RedmineWithGit
2
+ module Load
3
+ class All < ::RedmineWithGit::Load::Base
4
+ include ::RedmineWithGit::DumpLoad::All
5
+
6
+ private
7
+
8
+ def run_clear
9
+ # Do nothing
10
+ end
11
+
12
+ def run_load
13
+ on_temp_dir do
14
+ extract_path_to_tmpdir
15
+ RESOURCES.each { |r| load_resource(r) }
16
+ end
17
+ end
18
+
19
+ def extract_path_to_tmpdir
20
+ tar_extract_command(tmpdir, false).execute!(input_file: path)
21
+ end
22
+
23
+ def load_resource(resource_name)
24
+ resource_class(resource_name).new(resource_file_path(resource_name))
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,51 @@
1
+ module RedmineWithGit
2
+ module Load
3
+ class Base < ::RedmineWithGit::DumpLoad::Base
4
+ private
5
+
6
+ def run
7
+ start_banner
8
+ unless ::File.exist?(path)
9
+ Rails.logger.warn "File \"#{path}\" does not exist"
10
+ return
11
+ end
12
+ run_clear
13
+ run_load
14
+ end_banner
15
+ end
16
+
17
+ def start_banner
18
+ Rails.logger.info "Loading \"#{path}\" to #{resource_name}..."
19
+ Rails.logger.info("#{path}: #{number_to_human_size(::File.size(path))}, #{path_type}")
20
+ end
21
+
22
+ def run_clear
23
+ Rails.logger.info "Clearing resource \"#{resource_name}\"..."
24
+ before_clear
25
+ clear_command.execute!
26
+ end
27
+
28
+ def run_load
29
+ Rails.logger.info "Loading \"#{path}\" to resource \"#{resource_name}\"..."
30
+ load_command.execute!(input_file: path)
31
+ after_load
32
+ end
33
+
34
+ def end_banner
35
+ Rails.logger.info "\"#{path}\" loaded in resource \"#{resource_name}\""
36
+ end
37
+
38
+ def uncompress_args
39
+ ['gzip', '-d', '-c', '-']
40
+ end
41
+
42
+ def tar_extract_command(target_dir, compression = true)
43
+ env.command('tar', (compression ? '-xz' : '-x'), '-C', target_dir)
44
+ end
45
+
46
+ def before_clear; end
47
+
48
+ def after_load; end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,48 @@
1
+ require_dependency 'redmine_plugins_helper'
2
+
3
+ module RedmineWithGit
4
+ module Load
5
+ class Database < ::RedmineWithGit::Load::Base
6
+ include ::RedmineWithGit::DumpLoad::Database
7
+
8
+ private
9
+
10
+ def before_clear
11
+ raise(<<EOS) unless ::RedminePluginsHelper.settings_table_exist?
12
+ Settings table does not exist.
13
+ EOS
14
+ @redmine_git_hosting_setting = ::Setting.plugin_redmine_git_hosting
15
+ end
16
+
17
+ def clear_command
18
+ psql_sql_command(psql_sql_command(drop_all_tables_sql).execute!)
19
+ end
20
+
21
+ def load_command
22
+ psql_command.prepend(uncompress_args + ['@ESC_|'])
23
+ end
24
+
25
+ def after_load
26
+ ::Setting.plugin_redmine_git_hosting = @redmine_git_hosting_setting if
27
+ @redmine_git_hosting_setting
28
+ end
29
+
30
+ def psql_command
31
+ env.command(
32
+ [password_arg, 'psql',
33
+ '-h', database_schema['host'], '-U', database_schema['username'], '-d',
34
+ database_schema['database']]
35
+ )
36
+ end
37
+
38
+ def psql_sql_command(sql)
39
+ psql_command.append(['-qtc', sql])
40
+ end
41
+
42
+ def drop_all_tables_sql
43
+ "select 'drop table \"' || tablename || '\" cascade;' from pg_tables " \
44
+ "where schemaname = 'public';"
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,17 @@
1
+ module RedmineWithGit
2
+ module Load
3
+ class Files < ::RedmineWithGit::Load::Base
4
+ include ::RedmineWithGit::DumpLoad::Files
5
+
6
+ private
7
+
8
+ def clear_command
9
+ env.command('rm', '-rf', "#{files_path}/*")
10
+ end
11
+
12
+ def load_command
13
+ tar_extract_command(files_path)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ module RedmineWithGit
2
+ module Load
3
+ class Git < ::RedmineWithGit::Load::Base
4
+ include ::RedmineWithGit::DumpLoad::Git
5
+
6
+ private
7
+
8
+ def clear_command
9
+ env.command('rm', '-rf', "#{repositories_path}/*").prepend(sudo_command)
10
+ end
11
+
12
+ def run_load
13
+ env.command('mkdir', '-p', repositories_path).prepend(sudo_command).execute!
14
+ super
15
+ end
16
+
17
+ def load_command
18
+ tar_extract_command(repositories_path).prepend(sudo_command)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RedmineWithGit
4
+ VERSION = '0.1.4'.freeze
5
+ end
@@ -0,0 +1,28 @@
1
+ namespace :redmine_with_git do
2
+ %w(database files git all).each do |a|
3
+ namespace :dump do
4
+ task a, [:path, :overwrite] => :environment do |_t, args|
5
+ ::RedmineWithGit::Dump.const_get(a.camelize).new(args.path, args.overwrite.present?)
6
+ end
7
+ end
8
+ namespace :load do
9
+ task a, [:path] => :environment do |_t, args|
10
+ ::RedmineWithGit::Load.const_get(a.camelize).new(args.path)
11
+ end
12
+ end
13
+ end
14
+
15
+ desc 'Executa as operações de "Rescue" da configuração do plugin RedmineGitHosting'
16
+ task rescue: [:'redmine_git_hosting:install_hook_parameters',
17
+ :'redmine_git_hosting:migration_tools:update_repositories_type',
18
+ :'redmine_git_hosting:install_hook_files',
19
+ :'redmine_git_hosting:fetch_changesets'] do |_t, _args|
20
+ RedmineGitHosting::GitoliteAccessor.update_projects(
21
+ 'all',
22
+ message: 'Forced resync of all projects (active, closed, archived)...',
23
+ force: true
24
+ )
25
+ RedmineGitHosting::GitoliteAccessor.resync_ssh_keys
26
+ RedmineGitHosting::GitoliteAccessor.flush_git_cache
27
+ end
28
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redmine_with_git
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4
5
+ platform: ruby
6
+ authors:
7
+ - Esquilo Azul Company
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-04-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: eac_rails_utils
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: eac_ruby_utils
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.1'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 0.1.2
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '0.1'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 0.1.2
47
+ description:
48
+ email:
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - app/controllers/redmine_with_git_controller.rb
54
+ - app/helpers/redmine_with_git_helper.rb
55
+ - app/models/redmine_with_git/tableless/load.rb
56
+ - app/views/redmine_with_git/_api.html.erb
57
+ - app/views/redmine_with_git/_export.html.erb
58
+ - app/views/redmine_with_git/_import.html.erb
59
+ - app/views/redmine_with_git/index.html.erb
60
+ - config/initializers/000_dependencies.rb
61
+ - config/locales/en.yml
62
+ - config/locales/pt-BR.yml
63
+ - config/routes.rb
64
+ - init.rb
65
+ - lib/redmine_with_git/dump/all.rb
66
+ - lib/redmine_with_git/dump/base.rb
67
+ - lib/redmine_with_git/dump/database.rb
68
+ - lib/redmine_with_git/dump/files.rb
69
+ - lib/redmine_with_git/dump/git.rb
70
+ - lib/redmine_with_git/dump_load/all.rb
71
+ - lib/redmine_with_git/dump_load/base.rb
72
+ - lib/redmine_with_git/dump_load/database.rb
73
+ - lib/redmine_with_git/dump_load/files.rb
74
+ - lib/redmine_with_git/dump_load/git.rb
75
+ - lib/redmine_with_git/load/all.rb
76
+ - lib/redmine_with_git/load/base.rb
77
+ - lib/redmine_with_git/load/database.rb
78
+ - lib/redmine_with_git/load/files.rb
79
+ - lib/redmine_with_git/load/git.rb
80
+ - lib/redmine_with_git/version.rb
81
+ - lib/tasks/redmine_with_git.rake
82
+ homepage:
83
+ licenses: []
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 2.7.7
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: Additional features for RedmineGitHosting.
105
+ test_files: []