1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#!/usr/bin/env ruby
#
# Find dependencies for an Omnibus software component.
#
# Copyright (C) 2014 Codethink Limited
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
require 'bundler'
require_relative 'importer_base'
require_relative 'importer_omnibus_extensions'
BANNER = "Usage: omnibus.find_deps PROJECT_DIR PROJECT_NAME SOURCE_DIR SOFTWARE_NAME"
DESCRIPTION = <<-END
Calculate dependencies for a given Omnibus software component.
END
class OmnibusDependencyFinder < Importer::Base
def initialize
local_data = YAML.load_file(local_data_path("omnibus.yaml"))
@dependency_blacklist = local_data['dependency-blacklist']
end
def parse_options(arguments)
opts = create_option_parser(BANNER, DESCRIPTION)
parsed_arguments = opts.parse!(arguments)
if parsed_arguments.length != 4 and parsed_arguments.length != 5
STDERR.puts "Expected 4 or 5 arguments, got #{parsed_arguments}."
opts.parse(['-?'])
exit 255
end
project_dir, project_name, source_dir, software_name, expected_version = \
parsed_arguments
# Not yet implemented
#if expected_version != nil
# expected_version = Gem::Version.new(expected_version)
#end
[project_dir, project_name, source_dir, software_name, expected_version]
end
def resolve_rubygems_deps(requirements)
return {} if requirements.empty?
log.info('Resolving RubyGem requirements with Bundler')
fake_gemfile = Bundler::Dsl.new
fake_gemfile.source('https://rubygems.org')
requirements.each do |dep|
fake_gemfile.gem(dep.name, dep.requirement)
end
definition = fake_gemfile.to_definition('Gemfile.lock', true)
resolved_specs = definition.resolve_remotely!
Hash[resolved_specs.collect { |spec| [spec.name, spec.version.to_s]}]
end
def calculate_dependencies_for_software(project, software, source_dir)
omnibus_deps = {}
rubygems_deps = {}
software.dependencies.each do |name|
software = Omnibus::Software.load(project, name)
if @dependency_blacklist.member? name
log.info(
"Not adding #{name} as a dependency as it is marked to be ignored.")
elsif software.fetcher.instance_of?(Omnibus::PathFetcher)
log.info(
"Not adding #{name} as a dependency: it's installed from " +
"a path which probably means that it is package configuration, not " +
"a 3rd-party component to be imported.")
elsif software.fetcher.instance_of?(Omnibus::NullFetcher)
if software.builder.built_gemspec
log.info(
"Adding #{name} as a RubyGem dependency because it builds " +
"#{software.builder.built_gemspec}")
rubygems_deps[name] = software.version
else
log.info(
"Not adding #{name} as a dependency: no sources listed.")
end
else
omnibus_deps[name] = software.version
end
end
gem_requirements = software.builder.manually_installed_rubygems
rubygems_deps = resolve_rubygems_deps(gem_requirements)
{
"omnibus" => {
# FIXME: are these build or runtime dependencies? We'll assume both.
"build-dependencies" => omnibus_deps,
"runtime-dependencies" => omnibus_deps,
},
"rubygems" => {
"build-dependencies" => {},
"runtime-dependencies" => rubygems_deps,
}
}
end
def run
project_dir, project_name, source_dir, software_name = parse_options(ARGV)
log.info("Calculating dependencies for #{software_name} from project " +
"#{project_name}, defined in #{project_dir}")
Dir.chdir(project_dir)
project = Omnibus::Project.load(project_name)
software = Omnibus::Software.load(@project, software_name)
dependencies = calculate_dependencies_for_software(
project, software, source_dir)
write_dependencies(STDOUT, dependencies)
end
end
OmnibusDependencyFinder.new.run
|