rys-bundler 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +6 -0
- data/lib/rys/bundler/command.rb +51 -0
- data/lib/rys/bundler/commands/add.rb +14 -0
- data/lib/rys/bundler/commands/base.rb +57 -0
- data/lib/rys/bundler/commands/build.rb +269 -0
- data/lib/rys/bundler/commands/build_deployment.rb +30 -0
- data/lib/rys/bundler/commands/build_interactively.rb +14 -0
- data/lib/rys/bundler/commands/build_local.rb +28 -0
- data/lib/rys/bundler/hooks.rb +292 -0
- data/lib/rys/bundler/version.rb +5 -0
- data/lib/rys/bundler.rb +17 -0
- data/lib/rys-bundler.rb +1 -0
- metadata +68 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c463d41d628123e4c1e09b444a903076cd13fda6436c2a25c9ef6ff3594cae5f
|
4
|
+
data.tar.gz: 3c4ee5081c2789809bcb9359a5253c6b135d700174c27d75229538b082a48e02
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f7d2a5463ec8bd83f2465726ef929ab6c5b697b4a4f1465ea0eb9497ea6d9a2c98ab38a36c46d2b17fd2aca5f260f3fcecf6ec0af56ab1c8d4cc01df0b4eacea
|
7
|
+
data.tar.gz: 6fefbbd224b6b032ee867423b1b09ddedff97713fc84246a957bd289b9ba53a2f9b8a3bbd5fc11dc665999c44ad4c49dbb690226b7e65a8722c421f85d98331f
|
data/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Rys
|
2
|
+
module Bundler
|
3
|
+
class Command
|
4
|
+
|
5
|
+
# For now only "rys" command is available
|
6
|
+
def exec(command, args)
|
7
|
+
if args.include?('-h') || args.include?('--help')
|
8
|
+
print_help_and_exit
|
9
|
+
end
|
10
|
+
|
11
|
+
# To avoid deleting options
|
12
|
+
if args.first.to_s.start_with?('-')
|
13
|
+
action = ''
|
14
|
+
else
|
15
|
+
action = args.shift.to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
case action
|
19
|
+
when 'add'
|
20
|
+
Commands::Add.run(args)
|
21
|
+
when 'build', ''
|
22
|
+
Commands::Build.run(args)
|
23
|
+
when 'ibuild'
|
24
|
+
Commands::BuildInteractively.run(args)
|
25
|
+
when 'help'
|
26
|
+
print_help_and_exit
|
27
|
+
else
|
28
|
+
raise "Unknow action '#{action}'"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def print_help_and_exit
|
35
|
+
puts %{USAGE: bundle rys ACTION [options]}
|
36
|
+
puts %{}
|
37
|
+
puts %{COMMANDS:}
|
38
|
+
puts %{ add Add a rys gem}
|
39
|
+
puts %{ build Build rys gems (download for development or deployment)}
|
40
|
+
puts %{ ibuild Build rys gems interactively}
|
41
|
+
puts %{}
|
42
|
+
puts %{OPTIONS:}
|
43
|
+
puts %{ -h, --help}
|
44
|
+
puts %{ Print this help}
|
45
|
+
puts %{}
|
46
|
+
exit
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'open3'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'optparse'
|
4
|
+
require 'tty-prompt'
|
5
|
+
|
6
|
+
module Rys
|
7
|
+
module Bundler
|
8
|
+
module Commands
|
9
|
+
class Base
|
10
|
+
|
11
|
+
def self.run(args)
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
def prompt
|
16
|
+
@prompt ||= TTY::Prompt.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def pastel
|
20
|
+
@pastel ||= Pastel.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def ui
|
24
|
+
::Bundler.ui
|
25
|
+
end
|
26
|
+
|
27
|
+
def run
|
28
|
+
raise NotImplementedError
|
29
|
+
end
|
30
|
+
|
31
|
+
def command(command)
|
32
|
+
output, status = Open3.capture2e(command)
|
33
|
+
|
34
|
+
if !status.success?
|
35
|
+
ui.error output
|
36
|
+
exit 1
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_redmine_plugin!
|
41
|
+
plugins_dir = Pathname.pwd.join('plugins')
|
42
|
+
plugins = Pathname.glob(plugins_dir.join('*/rys.rb'))
|
43
|
+
|
44
|
+
case plugins.size
|
45
|
+
when 0
|
46
|
+
raise 'There is no redmine plugin for rys gems. Please run "rails generate rys:redmine:plugin NAME"'
|
47
|
+
when 1
|
48
|
+
return plugins.first.dirname
|
49
|
+
else
|
50
|
+
raise 'There are more than one redmine plugin for rys plugins.'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,269 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Rys
|
5
|
+
module Bundler
|
6
|
+
module Commands
|
7
|
+
class Build < Base
|
8
|
+
|
9
|
+
COMMENT_PREFIX = '# RYS_BUILDER #'
|
10
|
+
|
11
|
+
attr_reader :options
|
12
|
+
|
13
|
+
def self.run(args)
|
14
|
+
options = OpenStruct.new
|
15
|
+
options.deployment = false
|
16
|
+
options.submodules = false
|
17
|
+
options.redmine_plugin = nil
|
18
|
+
|
19
|
+
OptionParser.new do |opts|
|
20
|
+
opts.banner = 'Usage: bundle rys build [options]'
|
21
|
+
|
22
|
+
opts.on('-d', '--deployment', 'Prepare gems for deployment') do |value|
|
23
|
+
options.deployment = value
|
24
|
+
end
|
25
|
+
|
26
|
+
# Quite a dangerous switch so do not add a short switch!!!
|
27
|
+
opts.on('--revert', 'Revert build (dangerous operation)') do |value|
|
28
|
+
options.revert = value
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on('-s', '--submodules', 'Add gems as submodules (experimental)') do |value|
|
32
|
+
options.submodules = value
|
33
|
+
abort('Not yet implemented')
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on('-r', '--redmine-plugin PATH', 'Redmine plugin for rys gems') do |value|
|
37
|
+
options.redmine_plugin = Pathname.new(value)
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
41
|
+
puts opts
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on_tail('-v', '--version', 'Show version') do
|
46
|
+
puts ::Rys::Bundler::VERSION
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
end.parse(args)
|
50
|
+
|
51
|
+
if options.deployment
|
52
|
+
klass = BuildDeployment
|
53
|
+
else
|
54
|
+
klass = BuildLocal
|
55
|
+
end
|
56
|
+
|
57
|
+
instance = klass.new(options)
|
58
|
+
|
59
|
+
if options.revert
|
60
|
+
instance.run_revert
|
61
|
+
else
|
62
|
+
instance.run
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def initialize(options)
|
67
|
+
@options = options
|
68
|
+
end
|
69
|
+
|
70
|
+
def run
|
71
|
+
prepare_target
|
72
|
+
prepare_to_copy
|
73
|
+
copy_dependencies
|
74
|
+
comment_copied
|
75
|
+
save_report
|
76
|
+
|
77
|
+
ui.info ''
|
78
|
+
ui.info 'You may want run bundle install again (just for sure)'
|
79
|
+
end
|
80
|
+
|
81
|
+
def run_revert
|
82
|
+
prepare_target
|
83
|
+
prepare_to_delete
|
84
|
+
delete_dependencies
|
85
|
+
uncomment_deleted
|
86
|
+
delete_report
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def short_filename(path)
|
92
|
+
path.each_filename.to_a.last(2).join('/')
|
93
|
+
end
|
94
|
+
|
95
|
+
def build_yml
|
96
|
+
@target.join('build.yml')
|
97
|
+
end
|
98
|
+
|
99
|
+
def print_gem_status(name, status)
|
100
|
+
ui.info (name + ' ').ljust(@dependency_ljust, '.') + " #{status}"
|
101
|
+
end
|
102
|
+
|
103
|
+
def prepare_target
|
104
|
+
if options.redmine_plugin&.directory?
|
105
|
+
@redmine_plugin = options.redmine_plugin
|
106
|
+
else
|
107
|
+
@redmine_plugin = get_redmine_plugin!
|
108
|
+
end
|
109
|
+
|
110
|
+
@target = @redmine_plugin.join(default_target_dir)
|
111
|
+
FileUtils.mkdir_p(@target)
|
112
|
+
end
|
113
|
+
|
114
|
+
def prepare_to_copy
|
115
|
+
all_dependencies = ::Bundler.load.dependencies
|
116
|
+
@dependencies = all_dependencies.select do |dependency|
|
117
|
+
dependency.groups.include?(:rys)
|
118
|
+
end
|
119
|
+
@dependency_ljust = @dependencies.map{|d| d.name.size }.max.to_i + 4
|
120
|
+
end
|
121
|
+
|
122
|
+
def prepare_to_delete
|
123
|
+
@dependency_ljust = build_report.keys.map{|d| d.size }.max.to_i + 4
|
124
|
+
end
|
125
|
+
|
126
|
+
# Copy/clone/symlink/... all dependencies into proper directory
|
127
|
+
def copy_dependencies
|
128
|
+
@copied_gems = []
|
129
|
+
|
130
|
+
@dependencies.each do |dependency|
|
131
|
+
source = dependency.source
|
132
|
+
path = @target.join(dependency.name)
|
133
|
+
|
134
|
+
# This could happend if gem is loaded from `@target`
|
135
|
+
if path.directory?
|
136
|
+
print_gem_status(dependency.name, 'already exist')
|
137
|
+
next
|
138
|
+
end
|
139
|
+
|
140
|
+
case source
|
141
|
+
when ::Bundler::Source::Git
|
142
|
+
build_gem_from_git(dependency, source, path)
|
143
|
+
@copied_gems << dependency.name
|
144
|
+
|
145
|
+
when ::Bundler::Source::Path
|
146
|
+
build_gem_from_path(dependency, source, path)
|
147
|
+
@copied_gems << dependency.name
|
148
|
+
|
149
|
+
else
|
150
|
+
print_gem_status(dependency.name, 'be resolved automatically')
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def delete_dependencies
|
156
|
+
build_report.each do |gem_name, options|
|
157
|
+
path = @target.join(gem_name)
|
158
|
+
|
159
|
+
if File.symlink?(path)
|
160
|
+
FileUtils.rm(path)
|
161
|
+
print_gem_status(gem_name, 'symlink removed')
|
162
|
+
elsif File.directory?(path)
|
163
|
+
FileUtils.rm_rf(path)
|
164
|
+
print_gem_status(gem_name, 'directory removed')
|
165
|
+
else
|
166
|
+
print_gem_status(gem_name, 'not symlink or directory')
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def comment_copied
|
172
|
+
if @copied_gems.size == 0
|
173
|
+
return
|
174
|
+
end
|
175
|
+
|
176
|
+
ui.info ''
|
177
|
+
ui.info pastel.bold('Commenting gems')
|
178
|
+
::Bundler.definition.gemfiles.each do |gemfile|
|
179
|
+
gem_names = comment_gems_in(gemfile)
|
180
|
+
|
181
|
+
if gem_names.size > 0
|
182
|
+
gemfile_relative = gemfile.relative_path_from(::Bundler.root)
|
183
|
+
gem_names.each do |name|
|
184
|
+
build_report[name] = { 'origin' => gemfile_relative.to_s }
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
ui.info "* #{short_filename(gemfile)}: #{gem_names.size} occurrences"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def uncomment_deleted
|
193
|
+
ui.info ''
|
194
|
+
ui.info pastel.bold('Uncommenting gems')
|
195
|
+
|
196
|
+
all_origins = Hash.new { |hash, origin| hash[origin] = [] }
|
197
|
+
|
198
|
+
build_report.each do |gem_name, options|
|
199
|
+
all_origins[options['origin']] << gem_name
|
200
|
+
end
|
201
|
+
|
202
|
+
all_origins.each do |origin, gem_names|
|
203
|
+
origin_gemfile = ::Bundler.root.join(origin)
|
204
|
+
|
205
|
+
if origin_gemfile.exist?
|
206
|
+
gem_names = uncomment_gems_in(origin_gemfile, gem_names)
|
207
|
+
ui.info "* #{short_filename(origin_gemfile)}: #{gem_names.size} occurrences"
|
208
|
+
else
|
209
|
+
ui.info "* #{short_filename(origin_gemfile)}: not exist"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def build_report
|
215
|
+
@build_report ||= begin
|
216
|
+
if build_yml.exist?
|
217
|
+
YAML.load_file(build_yml)
|
218
|
+
else
|
219
|
+
{}
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def save_report
|
225
|
+
report = %{# This file was generated by Rys::Bundler at #{Time.now}\n}
|
226
|
+
report << %{# Modify file at your own risk\n}
|
227
|
+
report << build_report.to_yaml
|
228
|
+
|
229
|
+
build_yml.write(report)
|
230
|
+
end
|
231
|
+
|
232
|
+
def delete_report
|
233
|
+
build_yml.exist? && build_yml.delete
|
234
|
+
end
|
235
|
+
|
236
|
+
def comment_gems_in(path)
|
237
|
+
@comment_gems_pattern ||= /^(\s*)([^#|\n]*gem[ ]+["'](#{@copied_gems.join('|')})["'])/
|
238
|
+
|
239
|
+
names = []
|
240
|
+
content = File.binread(path)
|
241
|
+
content.gsub!(@comment_gems_pattern) do
|
242
|
+
names << $3
|
243
|
+
%{#{$1}#{COMMENT_PREFIX} #{$2}}
|
244
|
+
end
|
245
|
+
|
246
|
+
File.open(path, 'wb') { |file| file.write(content) }
|
247
|
+
names.uniq!
|
248
|
+
names
|
249
|
+
end
|
250
|
+
|
251
|
+
def uncomment_gems_in(path, gem_names)
|
252
|
+
pattern = /^(\s*)#{COMMENT_PREFIX}[ ]*(gem[ ]+["'](#{gem_names.join('|')})["'])/
|
253
|
+
|
254
|
+
names = []
|
255
|
+
content = File.binread(path)
|
256
|
+
content.gsub!(pattern) do
|
257
|
+
names << $3
|
258
|
+
%{#{$1}#{$2}}
|
259
|
+
end
|
260
|
+
|
261
|
+
File.open(path, 'wb') { |file| file.write(content) }
|
262
|
+
names.uniq!
|
263
|
+
names
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Rys
|
2
|
+
module Bundler
|
3
|
+
module Commands
|
4
|
+
class BuildDeployment < Build
|
5
|
+
|
6
|
+
def default_target_dir
|
7
|
+
'gems'
|
8
|
+
end
|
9
|
+
|
10
|
+
def build_gem_from_git(dependency, source, path)
|
11
|
+
if source.send(:local?)
|
12
|
+
FileUtils.cp_r(source.path, path)
|
13
|
+
print_gem_status(dependency.name, 'copied')
|
14
|
+
else
|
15
|
+
command %{git clone --depth=1 --branch="#{source.branch}" "#{source.uri}" "#{path}"}
|
16
|
+
print_gem_status(dependency.name, 'clonned')
|
17
|
+
end
|
18
|
+
|
19
|
+
FileUtils.rm_rf(path.join('.git'))
|
20
|
+
end
|
21
|
+
|
22
|
+
def build_gem_from_path(dependency, source, path)
|
23
|
+
FileUtils.cp_r(source.path, path)
|
24
|
+
print_gem_status(dependency.name, 'copied')
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Rys
|
2
|
+
module Bundler
|
3
|
+
module Commands
|
4
|
+
class BuildLocal < Build
|
5
|
+
|
6
|
+
def default_target_dir
|
7
|
+
'local'
|
8
|
+
end
|
9
|
+
|
10
|
+
def build_gem_from_git(dependency, source, path)
|
11
|
+
if source.send(:local?)
|
12
|
+
path.make_symlink(source.path)
|
13
|
+
print_gem_status(dependency.name, 'symlinked')
|
14
|
+
else
|
15
|
+
command %{git clone --branch="#{source.branch}" "#{source.uri}" "#{path}"}
|
16
|
+
print_gem_status(dependency.name, 'clonned')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def build_gem_from_path(dependency, source, path)
|
21
|
+
path.make_symlink(source.path)
|
22
|
+
print_gem_status(dependency.name, 'symlinked')
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,292 @@
|
|
1
|
+
##
|
2
|
+
# Dependencies tree can look like this
|
3
|
+
# (except it is even worse)
|
4
|
+
#
|
5
|
+
# You have to ensure that local dependencies (gemfile: `path: '...'`) are
|
6
|
+
# resolved prior to remote dependencies (gemfile: `git: '...'`) because not
|
7
|
+
# all users have rights for the repository (that is why packages are created).
|
8
|
+
#
|
9
|
+
# gems.rb
|
10
|
+
# |-- easy_twofa (local)
|
11
|
+
# | |-- rys (remote)
|
12
|
+
# | `-- easy_core (remote)
|
13
|
+
# |-- easy_contacts (local)
|
14
|
+
# | |-- easy_query (remote)
|
15
|
+
# | | |-- rys (remote)
|
16
|
+
# | | `-- easy_core(remote)
|
17
|
+
# | |-- rys (remote)
|
18
|
+
# | `-- easy_core (remote)
|
19
|
+
# |-- rys (local)
|
20
|
+
# |-- easy_core (local)
|
21
|
+
# | `-- rys (remote)
|
22
|
+
# |-- tty-prompt (remote)
|
23
|
+
# `-- easy_query (local)
|
24
|
+
# |-- easy_core (remote)
|
25
|
+
# `-- rys (remote)
|
26
|
+
#
|
27
|
+
module Rys
|
28
|
+
module Bundler
|
29
|
+
module Hooks
|
30
|
+
|
31
|
+
# Recursively searches for dependencies
|
32
|
+
# If there will be same dependencies => first won
|
33
|
+
#
|
34
|
+
# == Arguments:
|
35
|
+
# dependencies:: Array of dependencies which should be resolved
|
36
|
+
# new_dependencies:: All dependencies from resolving
|
37
|
+
# Array is in-place modified
|
38
|
+
# resolved_dependencies:: Already resolved dependencies
|
39
|
+
# For preventing loops
|
40
|
+
#
|
41
|
+
def self.resolve_rys_dependencies(dependencies, new_dependencies, resolved_dependencies)
|
42
|
+
dependencies = prepare_dependencies_for_next_round(dependencies, resolved_dependencies)
|
43
|
+
|
44
|
+
# Resolving is done in next round
|
45
|
+
next_dependencies_to_resolve = []
|
46
|
+
|
47
|
+
dependencies.each do |dependency|
|
48
|
+
# To allow resolving
|
49
|
+
dependency.source.remote!
|
50
|
+
|
51
|
+
# Ensure gem (downloaded if necessary)
|
52
|
+
dependency.source.specs
|
53
|
+
|
54
|
+
# Get dependencies from this file using rys group
|
55
|
+
dependencies_rb = dependency.source.path.join('dependencies.rb')
|
56
|
+
|
57
|
+
if dependencies_rb.exist?
|
58
|
+
definition = ::Bundler::Dsl.evaluate(dependencies_rb, ::Bundler.default_lockfile, true)
|
59
|
+
rys_group_dependencies = definition.dependencies.select{|dep| dep.groups.include?(:rys) }
|
60
|
+
|
61
|
+
new_dependencies.concat(rys_group_dependencies)
|
62
|
+
next_dependencies_to_resolve.concat(rys_group_dependencies)
|
63
|
+
end
|
64
|
+
|
65
|
+
resolved_dependencies << dependency
|
66
|
+
# add_source_definition(dependency, ::Bundler.definition)
|
67
|
+
end
|
68
|
+
|
69
|
+
if next_dependencies_to_resolve.size > 0
|
70
|
+
resolve_rys_dependencies(next_dependencies_to_resolve, new_dependencies, resolved_dependencies)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Be careful!!!
|
75
|
+
# There is a lot of possibilities for gem definition
|
76
|
+
#
|
77
|
+
# 1. Normal gem
|
78
|
+
# 2. Gem on git (download)
|
79
|
+
# 3. Gem on git (not-downloaded)
|
80
|
+
# 4. Gem on git locally overriden
|
81
|
+
# 5. Gem on local disk
|
82
|
+
#
|
83
|
+
def self.before_install_all(dependencies)
|
84
|
+
new_dependencies = []
|
85
|
+
resolved_dependencies = []
|
86
|
+
resolve_rys_dependencies(dependencies, new_dependencies, resolved_dependencies)
|
87
|
+
|
88
|
+
# Select only missing dependencies so user can
|
89
|
+
# rewrite each dependecny in main gems.rb
|
90
|
+
new_dependencies = new_dependencies.uniq(&:name)
|
91
|
+
new_dependencies.reject! do |dep1|
|
92
|
+
dependencies.any? do |dep2|
|
93
|
+
dep1.name == dep2.name && !dep2.groups.include?(:__dependencies__)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Adding sources from new dependecies
|
98
|
+
# Needef for Path or Git
|
99
|
+
new_dependencies.each do |dependency|
|
100
|
+
next if !dependency.source
|
101
|
+
sources = ::Bundler.definition.send(:sources).send(:source_list_for, dependency.source)
|
102
|
+
sources << dependency.source
|
103
|
+
end
|
104
|
+
|
105
|
+
::Bundler.ui.info "Added #{new_dependencies.size} new dependencies"
|
106
|
+
|
107
|
+
# Concat them to main Bundler.definition.dependencies
|
108
|
+
dependencies.concat(new_dependencies)
|
109
|
+
|
110
|
+
# Save them for Bundler.require (rails config/boot.rb)
|
111
|
+
save_new_dependencies(new_dependencies)
|
112
|
+
|
113
|
+
# To ensure main bundler download plugins
|
114
|
+
::Bundler.definition.instance_eval do
|
115
|
+
@dependency_changes = true
|
116
|
+
# @local_changes = converge_locals
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.rys_gemfile(dsl)
|
121
|
+
# Loading dependencies brings some troubles. For example if main
|
122
|
+
# app add a gem which already exist as dependencies. There could
|
123
|
+
# be conflicts. To avoid some of problems - dependencies are
|
124
|
+
# loaded only if there is not a lock file (bundler wasn't
|
125
|
+
# launched or user want force install).
|
126
|
+
return if !::Bundler.root.join('gems.locked').exist? && !::Bundler.root.join('Gemfile.lock').exist?
|
127
|
+
|
128
|
+
if gems_dependencies_rb.exist?
|
129
|
+
# Mark gems as dependencies to be rewritten in a hook
|
130
|
+
# Because you dont know if:
|
131
|
+
# - gems are loaded for rails
|
132
|
+
# - running bundle install
|
133
|
+
# - bundle exec
|
134
|
+
# - or something else
|
135
|
+
dsl.group(:__dependencies__) do
|
136
|
+
dsl.eval_gemfile(gems_dependencies_rb)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Load gems from dummy path
|
142
|
+
# Conflicts are ingnored
|
143
|
+
#
|
144
|
+
def self.rys_load_dummy(dsl, dummy_path=nil)
|
145
|
+
possible_app_dirs = [
|
146
|
+
dummy_path,
|
147
|
+
ENV['DUMMY_PATH'],
|
148
|
+
::Bundler.root.join('test/dummy')
|
149
|
+
]
|
150
|
+
|
151
|
+
possible_app_dirs.each do |dir|
|
152
|
+
next if !dir
|
153
|
+
next if !File.directory?(dir)
|
154
|
+
|
155
|
+
['Gemfile', 'gems.rb'].each do |gems_rb|
|
156
|
+
gems_rb = File.expand_path(File.join(dir, gems_rb))
|
157
|
+
|
158
|
+
if File.exist?(gems_rb)
|
159
|
+
dsl.instance_eval do
|
160
|
+
|
161
|
+
# Patch method `gem` to avoid duplicit definition
|
162
|
+
# For example you can test rys 'ondra' but its
|
163
|
+
# already included in main app gemfile.
|
164
|
+
if is_a?(::Bundler::Plugin::DSL)
|
165
|
+
# gem methods is not defined here
|
166
|
+
else
|
167
|
+
singleton_class.class_eval do
|
168
|
+
alias_method :original_gem, :gem
|
169
|
+
end
|
170
|
+
|
171
|
+
def gem(name, *args)
|
172
|
+
if @dependencies.any? {|d| d.name == name }
|
173
|
+
::Bundler.ui.info "Skipping gem '#{name}' because already exist"
|
174
|
+
else
|
175
|
+
original_gem(name, *args)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
eval_gemfile(gems_rb)
|
181
|
+
end
|
182
|
+
|
183
|
+
return
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def self.gems_dependencies_rb
|
190
|
+
::Bundler.root.join('gems.dependencies.rb')
|
191
|
+
end
|
192
|
+
|
193
|
+
def self.prepare_dependencies_for_next_round(dependencies, resolved_dependencies)
|
194
|
+
dependencies = dependencies.dup
|
195
|
+
|
196
|
+
# Prepare dependencies
|
197
|
+
dependencies.keep_if do |dependency|
|
198
|
+
dependency.groups.include?(:rys) &&
|
199
|
+
dependency.source &&
|
200
|
+
resolved_dependencies.none?{|rd| rd.name == dependency.name }
|
201
|
+
end
|
202
|
+
|
203
|
+
# Sort them to prior local dependencies
|
204
|
+
dependencies.sort_by! do |dependency|
|
205
|
+
case dependency.source
|
206
|
+
# Git should be first because its inherit from Path
|
207
|
+
when ::Bundler::Source::Git
|
208
|
+
if dependency.source.send(:local?)
|
209
|
+
1
|
210
|
+
else
|
211
|
+
3
|
212
|
+
end
|
213
|
+
# Local path
|
214
|
+
when ::Bundler::Source::Path
|
215
|
+
0
|
216
|
+
# Rubygems, gemspec, metadata
|
217
|
+
else
|
218
|
+
2
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# More dependencies can depend on the same dependencies :-)
|
223
|
+
dependencies.uniq!(&:name)
|
224
|
+
|
225
|
+
return dependencies
|
226
|
+
end
|
227
|
+
|
228
|
+
def self.merge_definition_sources(from_definition, to_definition)
|
229
|
+
to_sources = to_definition.send(:sources)
|
230
|
+
|
231
|
+
from_definition.send(:sources).all_sources.map do |source|
|
232
|
+
begin
|
233
|
+
to_sources.send(:source_list_for, source) << source
|
234
|
+
rescue
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def self.add_source_definition(dependency, to_definition)
|
240
|
+
sources = to_definition.send(:sources).send(:source_list_for, dependency.source)
|
241
|
+
|
242
|
+
if sources.include?(dependency.source)
|
243
|
+
# Already there
|
244
|
+
else
|
245
|
+
sources << dependency.source
|
246
|
+
end
|
247
|
+
rescue
|
248
|
+
# Bundler could raise an ArgumentError
|
249
|
+
end
|
250
|
+
|
251
|
+
def self.save_new_dependencies(dependencies)
|
252
|
+
File.open(gems_dependencies_rb, 'w') do |f|
|
253
|
+
f.puts %{# This file was generated by Rys::Bundler at #{Time.now}}
|
254
|
+
f.puts %{# Dependencies are generated after every `bundle` command}
|
255
|
+
f.puts %{# Modify file at your own risk}
|
256
|
+
f.puts
|
257
|
+
|
258
|
+
dependencies.each do |dep|
|
259
|
+
options = {}
|
260
|
+
|
261
|
+
source = dep.source
|
262
|
+
case source
|
263
|
+
when ::Bundler::Source::Git
|
264
|
+
options[:git] = source.uri
|
265
|
+
options[:branch] = source.branch
|
266
|
+
options[:ref] = source.ref
|
267
|
+
when NilClass
|
268
|
+
# Regular gem
|
269
|
+
else
|
270
|
+
raise "Unknow source '#{source.class}'"
|
271
|
+
end
|
272
|
+
|
273
|
+
args = []
|
274
|
+
args << dep.name
|
275
|
+
args.concat(dep.requirement.as_list)
|
276
|
+
|
277
|
+
options[:groups] = dep.groups
|
278
|
+
options[:require] = dep.autorequire if dep.autorequire
|
279
|
+
|
280
|
+
gem_args = args.map{|arg| '"' + arg + '"' }.join(', ')
|
281
|
+
|
282
|
+
f.puts %{if dependencies.none?{|dep| dep.name.to_s == "#{dep.name}" }}
|
283
|
+
f.puts %{ gem #{gem_args}, #{options}}
|
284
|
+
f.puts %{end}
|
285
|
+
f.puts
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
data/lib/rys/bundler.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rys/bundler/version'
|
2
|
+
|
3
|
+
module Rys
|
4
|
+
module Bundler
|
5
|
+
autoload :Hooks, 'rys/bundler/hooks'
|
6
|
+
autoload :Command, 'rys/bundler/command'
|
7
|
+
|
8
|
+
module Commands
|
9
|
+
autoload :Base, 'rys/bundler/commands/base'
|
10
|
+
autoload :Add, 'rys/bundler/commands/add'
|
11
|
+
autoload :Build, 'rys/bundler/commands/build'
|
12
|
+
autoload :BuildLocal, 'rys/bundler/commands/build_local'
|
13
|
+
autoload :BuildDeployment, 'rys/bundler/commands/build_deployment'
|
14
|
+
autoload :BuildInteractively, 'rys/bundler/commands/build_interactively'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/rys-bundler.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'rys/bundler'
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rys-bundler
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ondřej Moravčík
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-10-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: tty-prompt
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description:
|
28
|
+
email:
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- README.md
|
34
|
+
- lib/rys-bundler.rb
|
35
|
+
- lib/rys/bundler.rb
|
36
|
+
- lib/rys/bundler/command.rb
|
37
|
+
- lib/rys/bundler/commands/add.rb
|
38
|
+
- lib/rys/bundler/commands/base.rb
|
39
|
+
- lib/rys/bundler/commands/build.rb
|
40
|
+
- lib/rys/bundler/commands/build_deployment.rb
|
41
|
+
- lib/rys/bundler/commands/build_interactively.rb
|
42
|
+
- lib/rys/bundler/commands/build_local.rb
|
43
|
+
- lib/rys/bundler/hooks.rb
|
44
|
+
- lib/rys/bundler/version.rb
|
45
|
+
homepage:
|
46
|
+
licenses: []
|
47
|
+
metadata: {}
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
requirements: []
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 2.7.6
|
65
|
+
signing_key:
|
66
|
+
specification_version: 4
|
67
|
+
summary: Recursively resolving rys dependencies
|
68
|
+
test_files: []
|