autoproj 2.0.0.rc4 → 2.0.0.rc5
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 +4 -4
- data/.travis.yml +4 -0
- data/bin/alocate +1 -1
- data/bin/autoproj +5 -4
- data/bin/autoproj_bootstrap +205 -26
- data/bin/autoproj_bootstrap.in +7 -1
- data/bin/autoproj_install +198 -25
- data/lib/autoproj.rb +1 -0
- data/lib/autoproj/cli.rb +1 -2
- data/lib/autoproj/cli/commit.rb +1 -2
- data/lib/autoproj/cli/locate.rb +4 -3
- data/lib/autoproj/cli/log.rb +0 -1
- data/lib/autoproj/cli/main.rb +24 -6
- data/lib/autoproj/cli/reset.rb +1 -0
- data/lib/autoproj/cli/status.rb +3 -2
- data/lib/autoproj/cli/tag.rb +8 -3
- data/lib/autoproj/cli/upgrade.rb +43 -39
- data/lib/autoproj/environment.rb +8 -0
- data/lib/autoproj/exceptions.rb +4 -0
- data/lib/autoproj/find_workspace.rb +83 -0
- data/lib/autoproj/ops/install.rb +198 -25
- data/lib/autoproj/os_package_installer.rb +5 -1
- data/lib/autoproj/os_package_resolver.rb +15 -5
- data/lib/autoproj/package_managers/bundler_manager.rb +98 -46
- data/lib/autoproj/package_set.rb +4 -7
- data/lib/autoproj/reporter.rb +4 -0
- data/lib/autoproj/system.rb +2 -2
- data/lib/autoproj/version.rb +1 -1
- data/lib/autoproj/workspace.rb +7 -63
- metadata +3 -2
data/lib/autoproj.rb
CHANGED
data/lib/autoproj/cli.rb
CHANGED
data/lib/autoproj/cli/commit.rb
CHANGED
data/lib/autoproj/cli/locate.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'autoproj'
|
2
1
|
require 'autoproj/cli/base'
|
3
2
|
|
4
3
|
module Autoproj
|
@@ -13,10 +12,12 @@ def initialize(ws = nil)
|
|
13
12
|
super
|
14
13
|
self.ws.load_config
|
15
14
|
|
16
|
-
|
17
|
-
if !File.file?(
|
15
|
+
path = InstallationManifest.path_for_root(self.ws.root_dir)
|
16
|
+
if !File.file?(path)
|
18
17
|
raise ConfigError, "the installation manifest is not present, please run autoproj envsh to generate it"
|
19
18
|
end
|
19
|
+
|
20
|
+
@installation_manifest = Autoproj::InstallationManifest.new(path)
|
20
21
|
installation_manifest.load
|
21
22
|
end
|
22
23
|
|
data/lib/autoproj/cli/log.rb
CHANGED
data/lib/autoproj/cli/main.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'thor'
|
2
|
-
require 'autoproj'
|
3
2
|
require 'autoproj/cli/main_test'
|
4
3
|
|
5
4
|
module Autoproj
|
@@ -7,9 +6,6 @@ module CLI
|
|
7
6
|
def self.basic_setup
|
8
7
|
Encoding.default_internal = Encoding::UTF_8
|
9
8
|
Encoding.default_external = Encoding::UTF_8
|
10
|
-
|
11
|
-
Autobuild::Reporting << Autoproj::Reporter.new
|
12
|
-
Autobuild::Package.clear
|
13
9
|
end
|
14
10
|
|
15
11
|
class Main < Thor
|
@@ -67,6 +63,8 @@ def envsh
|
|
67
63
|
desc: "compare to the given baseline. if 'true', the comparison will ignore any override, otherwise it will take into account overrides only up to the given package set"
|
68
64
|
option :snapshot, type: :boolean, default: false,
|
69
65
|
desc: "use the VCS information as 'versions --no-local' would detect it instead of the one in the configuration"
|
66
|
+
option :parallel, aliases: :p, type: :numeric,
|
67
|
+
desc: 'maximum number of parallel jobs'
|
70
68
|
def status(*packages)
|
71
69
|
run_autoproj_cli(:status, :Status, Hash[], *packages)
|
72
70
|
end
|
@@ -312,9 +310,29 @@ def query(query_string = nil)
|
|
312
310
|
run_autoproj_cli(:query, :Query, Hash[], *Array(query_string))
|
313
311
|
end
|
314
312
|
|
315
|
-
desc "upgrade autoproj itself"
|
313
|
+
desc 'upgrade', "upgrade autoproj itself, and the workspace layout"
|
314
|
+
option :local, type: :boolean, default: false,
|
315
|
+
desc: 'do not access the network (will fail if some gems are missing)'
|
316
|
+
option :gemfile, type: :string,
|
317
|
+
desc: 'path to a gemfile that should be used to install autoproj'
|
318
|
+
option :private_bundler, type: :boolean,
|
319
|
+
desc: 'install bundler inside the workspace instead of using the default Gem location'
|
320
|
+
option :private_gems, type: :boolean,
|
321
|
+
desc: 'install gems inside the workspace instead of using the default Gem location'
|
322
|
+
option :private_autoproj, type: :boolean,
|
323
|
+
desc: 'install bundler inside the workspace instead of using the default Gem location'
|
324
|
+
option :private, type: :boolean,
|
325
|
+
desc: 'equivalent to --private-bundler --private-autoproj --private-gems'
|
316
326
|
def upgrade
|
317
|
-
|
327
|
+
require 'autoproj/cli/upgrade'
|
328
|
+
Autoproj::CLI::Upgrade.new.run(options)
|
329
|
+
end
|
330
|
+
|
331
|
+
desc 'install_stage2 ROOT_DIR', 'used by autoproj_install to finalize the installation',
|
332
|
+
hide: true
|
333
|
+
def install_stage2(root_dir)
|
334
|
+
require 'autoproj/ops/install'
|
335
|
+
Autoproj::Ops::Install.new(root_dir).run(stage2: true)
|
318
336
|
end
|
319
337
|
end
|
320
338
|
end
|
data/lib/autoproj/cli/reset.rb
CHANGED
data/lib/autoproj/cli/status.rb
CHANGED
@@ -31,7 +31,7 @@ def run(user_selection, options = Hash.new)
|
|
31
31
|
pkg_sets = ws.manifest.each_package_set.to_a
|
32
32
|
if !pkg_sets.empty?
|
33
33
|
Autoproj.message("autoproj: displaying status of configuration", :bold)
|
34
|
-
display_status(pkg_sets, snapshot: options[:snapshot], only_local: options[:only_local])
|
34
|
+
display_status(pkg_sets, parallel: options[:parallel], snapshot: options[:snapshot], only_local: options[:only_local])
|
35
35
|
STDERR.puts
|
36
36
|
end
|
37
37
|
end
|
@@ -133,7 +133,8 @@ def status_of_package(package_description, options = Hash.new)
|
|
133
133
|
def display_status(packages, options = Hash.new)
|
134
134
|
result = StatusResult.new
|
135
135
|
|
136
|
-
|
136
|
+
parallel = options[:parallel] || ws.config.parallel_import_level
|
137
|
+
executor = Concurrent::FixedThreadPool.new(parallel, max_length: 0)
|
137
138
|
interactive, noninteractive = packages.partition do |pkg|
|
138
139
|
pkg.autobuild.importer && pkg.autobuild.importer.interactive?
|
139
140
|
end
|
data/lib/autoproj/cli/tag.rb
CHANGED
@@ -6,8 +6,12 @@
|
|
6
6
|
module Autoproj
|
7
7
|
module CLI
|
8
8
|
class Tag < Base
|
9
|
-
def run(
|
10
|
-
|
9
|
+
def run(arguments, options = Hash.new)
|
10
|
+
tag_name, *user_selection = *arguments
|
11
|
+
ws.load_config
|
12
|
+
main_package_set = LocalPackageSet.new(ws.manifest, ws.config_dir)
|
13
|
+
|
14
|
+
pkg = main_package_set.create_autobuild_package
|
11
15
|
importer = pkg.importer
|
12
16
|
if !importer || !importer.kind_of?(Autobuild::Git)
|
13
17
|
raise ConfigError, "cannot use autoproj tag if the main configuration is not managed by git"
|
@@ -21,6 +25,7 @@ def run(tag_name, *user_selection, options = Hash.new)
|
|
21
25
|
importer = pkg.importer
|
22
26
|
all_tags = importer.run_git_bare(pkg, 'tag')
|
23
27
|
all_tags.sort.each do |tag|
|
28
|
+
next if tag =~ /\^/
|
24
29
|
begin importer.show(pkg, "refs/tags/#{tag}", versions_file)
|
25
30
|
puts tag
|
26
31
|
rescue Autobuild::PackageException
|
@@ -43,7 +48,7 @@ def run(tag_name, *user_selection, options = Hash.new)
|
|
43
48
|
Autoproj.message "creating versions file, this may take a while"
|
44
49
|
versions.run(user_selection,
|
45
50
|
package_sets: options[:package_sets],
|
46
|
-
|
51
|
+
save: io.path,
|
47
52
|
replace: true,
|
48
53
|
keep_going: options[:keep_going])
|
49
54
|
end
|
data/lib/autoproj/cli/upgrade.rb
CHANGED
@@ -1,47 +1,31 @@
|
|
1
|
+
require 'autoproj/ops/install'
|
2
|
+
require 'autoproj/find_workspace'
|
1
3
|
module Autoproj
|
2
4
|
module CLI
|
3
5
|
class Upgrade
|
4
|
-
def
|
5
|
-
@root_dir = root_dir
|
6
|
-
end
|
7
|
-
|
8
|
-
def upgrade_from_v2
|
9
|
-
require 'autoproj/ops/install'
|
10
|
-
installer = Autoproj::Ops::Install.new(root_dir)
|
6
|
+
def upgrade_from_v2(installer, options = Hash.new)
|
11
7
|
installer.install
|
12
8
|
end
|
13
9
|
|
14
|
-
def
|
15
|
-
|
16
|
-
while !path.root?
|
17
|
-
if (path + "autoproj").exist?
|
18
|
-
break
|
19
|
-
end
|
20
|
-
path = path.parent
|
21
|
-
end
|
10
|
+
def upgrade_from_v1(installer, options = Hash.new)
|
11
|
+
root_dir = installer.root_dir
|
22
12
|
|
23
|
-
if
|
24
|
-
|
13
|
+
# Save a backup of the existing env.sh (if the backup does not
|
14
|
+
# already exist) to make it easier for a user to downgrade
|
15
|
+
env_backup = File.join(root_dir, 'env.sh-autoproj-v1')
|
16
|
+
if !File.file?(env_backup)
|
17
|
+
FileUtils.cp File.join(root_dir, 'env.sh'), env_backup
|
25
18
|
end
|
26
19
|
|
27
|
-
# I don't know if this is still useful or not ... but it does not hurt
|
28
|
-
#
|
29
|
-
# Preventing backslashed in path, that might be confusing on some path compares
|
30
|
-
if Autobuild.windows?
|
31
|
-
result = result.gsub(/\\/,'/')
|
32
|
-
end
|
33
|
-
result
|
34
|
-
end
|
35
|
-
|
36
|
-
def upgrade_from_v1
|
37
20
|
# Do an install
|
38
|
-
require 'autoproj/ops/install'
|
39
|
-
installer = Autoproj::Ops::Install.new(root_dir)
|
40
21
|
installer.run
|
41
|
-
|
22
|
+
|
23
|
+
# Copy the current configuration, merging it with the autoproj
|
24
|
+
# 2.x attributes
|
42
25
|
current_config = File.open(File.join(root_dir, 'autoproj', 'config.yml')) do |io|
|
43
26
|
YAML.load(io)
|
44
27
|
end
|
28
|
+
config_file_path = File.join(root_dir, '.autoproj', 'config.yml')
|
45
29
|
new_config = File.open(config_file_path) do |io|
|
46
30
|
YAML.load(io)
|
47
31
|
end
|
@@ -49,20 +33,40 @@ def upgrade_from_v1
|
|
49
33
|
io.write YAML.dump(current_config.merge(new_config))
|
50
34
|
end
|
51
35
|
|
52
|
-
|
53
|
-
|
54
|
-
|
36
|
+
# Copy the remotes symlinks
|
37
|
+
FileUtils.cp_r File.join(root_dir, '.remotes'), File.join(root_dir, '.autoproj', 'remotes')
|
38
|
+
# Copy the installation manifest
|
39
|
+
FileUtils.cp File.join(root_dir, '.autoproj-installation-manifest'),
|
40
|
+
File.join(root_dir, '.autoproj', 'installation-manifest')
|
41
|
+
|
42
|
+
puts "now, open a new console, source env.sh and run"
|
43
|
+
puts " autoproj osdeps"
|
44
|
+
puts " autoproj envsh"
|
45
|
+
end
|
46
|
+
|
47
|
+
def create_installer(root_dir, options = Hash.new)
|
48
|
+
installer = Autoproj::Ops::Install.new(root_dir)
|
49
|
+
installer.local = options[:local]
|
50
|
+
installer.private_bundler = options[:private_bundler] || options[:private]
|
51
|
+
installer.private_autoproj = options[:private_autoproj] || options[:private]
|
52
|
+
installer.private_gems = options[:private_gems] || options[:private]
|
53
|
+
if gemfile_path = options[:gemfile]
|
54
|
+
installer.gemfile = File.read(gemfile_path)
|
55
|
+
end
|
56
|
+
installer
|
55
57
|
end
|
56
58
|
|
57
|
-
def run(
|
58
|
-
root_dir =
|
59
|
+
def run(options = Hash.new)
|
60
|
+
root_dir = Autoproj.find_v2_workspace_dir
|
59
61
|
if root_dir && File.directory?(File.join(root_dir, '.autoproj'))
|
60
|
-
|
62
|
+
installer = create_installer(root_dir, options)
|
63
|
+
return upgrade_from_v2(installer, options)
|
61
64
|
end
|
62
65
|
|
63
|
-
root_dir =
|
64
|
-
if root_dir && File.directory?(root_dir, '.gems')
|
65
|
-
|
66
|
+
root_dir = Autoproj.find_v1_workspace_dir
|
67
|
+
if root_dir && File.directory?(File.join(root_dir, '.gems'))
|
68
|
+
installer = create_installer(root_dir, options)
|
69
|
+
return upgrade_from_v1(installer, options)
|
66
70
|
end
|
67
71
|
end
|
68
72
|
end
|
data/lib/autoproj/environment.rb
CHANGED
@@ -8,8 +8,16 @@ class Environment < Autobuild::Environment
|
|
8
8
|
attr_reader :root_dir
|
9
9
|
|
10
10
|
def prepare(root_dir)
|
11
|
+
super()
|
12
|
+
|
11
13
|
@root_dir = root_dir
|
12
14
|
set 'AUTOPROJ_CURRENT_ROOT', root_dir
|
15
|
+
|
16
|
+
@original_env = original_env.map_value do |name, value|
|
17
|
+
filtered = value.split(File::PATH_SEPARATOR).
|
18
|
+
find_all { |p| !Workspace.in_autoproj_project?(p) }
|
19
|
+
filtered.join(File::PATH_SEPARATOR)
|
20
|
+
end
|
13
21
|
end
|
14
22
|
|
15
23
|
def expand(value)
|
data/lib/autoproj/exceptions.rb
CHANGED
@@ -49,6 +49,10 @@ class WorkspaceAlreadyCreated < RuntimeError; end
|
|
49
49
|
# Exception raised when looking for a workspace and it cannot be found
|
50
50
|
class NotWorkspace < RuntimeError; end
|
51
51
|
|
52
|
+
# Exception raised when the autoproj workspace changes and the current
|
53
|
+
# workspace is outdated
|
54
|
+
class OutdatedWorkspace < RuntimeError; end
|
55
|
+
|
52
56
|
# Exception raised when initializing on a workspace that is not the current
|
53
57
|
# one
|
54
58
|
class MismatchingWorkspace < RuntimeError; end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Autoproj
|
5
|
+
# The base path from which we search for workspaces
|
6
|
+
def self.defaulT_find_base_dir
|
7
|
+
ENV['AUTOPROJ_CURRENT_ROOT'] || Dir.pwd
|
8
|
+
end
|
9
|
+
|
10
|
+
# Looks for the autoproj workspace that is related to a given directory
|
11
|
+
#
|
12
|
+
# @return [String,nil]
|
13
|
+
def self.find_workspace_dir(base_dir = defaulT_find_base_dir)
|
14
|
+
find_v2_workspace_dir(base_dir)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Looks for the autoproj prefix that contains a given directory
|
18
|
+
#
|
19
|
+
# @return [String,nil]
|
20
|
+
def self.find_prefix_dir(base_dir = defaulT_find_base_dir)
|
21
|
+
find_v2_prefix_dir(base_dir)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @private
|
25
|
+
#
|
26
|
+
# Finds an autoproj "root directory" that contains a given directory. It
|
27
|
+
# can either be the root of a workspace or the root of an install
|
28
|
+
# directory
|
29
|
+
#
|
30
|
+
# @param [String] base_dir the start of the search
|
31
|
+
# @param [String] config_field_name the name of a field in the root's
|
32
|
+
# configuration file, that should be returned instead of the root
|
33
|
+
# itself
|
34
|
+
# @return [String,nil] the root of the workspace directory, or nil if
|
35
|
+
# there's none
|
36
|
+
def self.find_v2_root_dir(base_dir, config_field_name)
|
37
|
+
path = Pathname.new(base_dir)
|
38
|
+
while !path.root?
|
39
|
+
if (path + ".autoproj").exist?
|
40
|
+
break
|
41
|
+
end
|
42
|
+
path = path.parent
|
43
|
+
end
|
44
|
+
|
45
|
+
if path.root?
|
46
|
+
return
|
47
|
+
end
|
48
|
+
|
49
|
+
config_path = path + ".autoproj" + "config.yml"
|
50
|
+
if config_path.exist?
|
51
|
+
config = YAML.load(config_path.read) || Hash.new
|
52
|
+
result = config[config_field_name] || path.to_s
|
53
|
+
File.expand_path(result, path.to_s)
|
54
|
+
else
|
55
|
+
path.to_s
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# {#find_workspace_dir} for v2 workspaces
|
60
|
+
def self.find_v2_workspace_dir(base_dir = defaulT_find_base_dir)
|
61
|
+
find_v2_root_dir(base_dir, 'workspace')
|
62
|
+
end
|
63
|
+
|
64
|
+
# {#find_prefix_dir} for v2 workspaces
|
65
|
+
def self.find_v2_prefix_dir(base_dir = defaulT_find_base_dir)
|
66
|
+
find_v2_root_dir(base_dir, 'prefix')
|
67
|
+
end
|
68
|
+
|
69
|
+
# {#find_workspace_dir} for v1 workspaces
|
70
|
+
#
|
71
|
+
# Note that for v1 workspaces {#find_prefix_dir} cannot be implemented
|
72
|
+
def self.find_v1_workspace_dir(base_dir = defaulT_find_base_dir)
|
73
|
+
path = Pathname.new(base_dir)
|
74
|
+
while !path.root?
|
75
|
+
if (path + "autoproj").exist?
|
76
|
+
return path.to_s
|
77
|
+
end
|
78
|
+
path = path.parent
|
79
|
+
end
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
data/lib/autoproj/ops/install.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'pathname'
|
1
2
|
require 'optparse'
|
2
3
|
require 'fileutils'
|
3
4
|
require 'yaml'
|
@@ -10,19 +11,65 @@ module Ops
|
|
10
11
|
# It can be required standalone (i.e. does not depend on anything else than
|
11
12
|
# ruby and the ruby standard library)
|
12
13
|
class Install
|
14
|
+
class UnexpectedBinstub < RuntimeError; end
|
15
|
+
|
13
16
|
# The directory in which to install autoproj
|
14
17
|
attr_reader :root_dir
|
15
18
|
# Content of the Gemfile generated to install autoproj itself
|
16
19
|
attr_accessor :gemfile
|
20
|
+
# The environment that is passed to the bundler installs
|
21
|
+
attr_reader :env
|
17
22
|
|
18
23
|
def initialize(root_dir)
|
19
24
|
@root_dir = root_dir
|
20
|
-
|
25
|
+
if File.file?(autoproj_gemfile_path)
|
26
|
+
@gemfile = File.read(autoproj_gemfile_path)
|
27
|
+
else
|
28
|
+
@gemfile = default_gemfile_contents
|
29
|
+
end
|
30
|
+
|
21
31
|
@private_bundler = false
|
22
32
|
@private_autoproj = false
|
23
33
|
@private_gems = false
|
34
|
+
@local = false
|
35
|
+
@env = self.class.clean_env
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.clean_env
|
39
|
+
env = Hash.new
|
40
|
+
env['RUBYLIB'] = []
|
41
|
+
env['GEM_PATH'] = []
|
42
|
+
%w{PATH GEM_HOME}.each do |name|
|
43
|
+
env[name] = sanitize_env(ENV[name] || "")
|
44
|
+
end
|
45
|
+
env['BUNDLE_GEMFILE'] = nil
|
46
|
+
env
|
24
47
|
end
|
25
48
|
|
49
|
+
def env_for_child
|
50
|
+
env.inject(Hash.new) do |h, (k, v)|
|
51
|
+
h[k] = (v.join(File::PATH_SEPARATOR) if v && !v.empty?)
|
52
|
+
h
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.sanitize_env(value)
|
57
|
+
value.split(File::PATH_SEPARATOR).
|
58
|
+
find_all { |p| !in_workspace?(p) }
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.in_workspace?(base_dir)
|
62
|
+
path = Pathname.new(base_dir)
|
63
|
+
while !path.root?
|
64
|
+
if (path + ".autoproj").exist? || (path + "autoproj").exist?
|
65
|
+
return true
|
66
|
+
end
|
67
|
+
path = path.parent
|
68
|
+
end
|
69
|
+
return false
|
70
|
+
end
|
71
|
+
|
72
|
+
|
26
73
|
def dot_autoproj; File.join(root_dir, '.autoproj') end
|
27
74
|
def bin_dir; File.join(dot_autoproj, 'bin') end
|
28
75
|
def bundler_install_dir; File.join(dot_autoproj, 'bundler') end
|
@@ -31,13 +78,24 @@ def autoproj_install_dir; File.join(dot_autoproj, 'autoproj') end
|
|
31
78
|
def autoproj_gemfile_path; File.join(autoproj_install_dir, 'Gemfile') end
|
32
79
|
def autoproj_config_path; File.join(dot_autoproj, 'config.yml') end
|
33
80
|
|
81
|
+
# Whether we can access the network while installing
|
82
|
+
def local?; !!@local end
|
83
|
+
# (see #local?)
|
84
|
+
def local=(flag); @local = flag end
|
85
|
+
|
34
86
|
# Whether bundler should be installed locally in {#dot_autoproj}
|
35
87
|
def private_bundler?; @private_bundler end
|
88
|
+
# (see #private_bundler?)
|
89
|
+
def private_bundler=(flag); @private_bundler = flag end
|
36
90
|
# Whether autoproj should be installed locally in {#dot_autoproj}
|
37
91
|
def private_autoproj?; @private_autoproj end
|
92
|
+
# (see #private_autoproj?)
|
93
|
+
def private_autoproj=(flag); @private_autoproj = flag end
|
38
94
|
# Whether bundler should be installed locally in the workspace
|
39
95
|
# prefix directory
|
40
96
|
def private_gems?; @private_gems end
|
97
|
+
# (see #private_gems?)
|
98
|
+
def private_gems=(flag); @private_gems = flag end
|
41
99
|
|
42
100
|
def guess_gem_program
|
43
101
|
ruby_bin = RbConfig::CONFIG['RUBY_INSTALL_NAME']
|
@@ -61,14 +119,18 @@ def guess_gem_program
|
|
61
119
|
# @param [String] autoproj_version a constraint on the autoproj version
|
62
120
|
# that should be used
|
63
121
|
# @return [String]
|
64
|
-
def default_gemfile_contents(autoproj_version = ">= 0")
|
122
|
+
def default_gemfile_contents(autoproj_version = ">= 2.0.0.a")
|
65
123
|
["source \"https://rubygems.org\"",
|
66
|
-
"gem \"autoproj\", \"#{autoproj_version}\""
|
124
|
+
"gem \"autoproj\", \"#{autoproj_version}\"",
|
125
|
+
"gem \"utilrb\", \">= 3.0.0.a\""].join("\n")
|
67
126
|
end
|
68
127
|
|
69
128
|
# Parse the provided command line options and returns the non-options
|
70
129
|
def parse_options(args = ARGV)
|
71
130
|
options = OptionParser.new do |opt|
|
131
|
+
opt.on '--local', 'do not access the network (may fail)' do
|
132
|
+
@local = true
|
133
|
+
end
|
72
134
|
opt.on '--private-bundler', 'install bundler locally in the workspace' do
|
73
135
|
@private_bundler = true
|
74
136
|
end
|
@@ -97,28 +159,37 @@ def install_bundler
|
|
97
159
|
gem_program = guess_gem_program
|
98
160
|
puts "Detected 'gem' to be #{gem_program}"
|
99
161
|
|
162
|
+
local = ['--local'] if local?
|
163
|
+
|
100
164
|
result = system(
|
101
|
-
|
102
|
-
'GEM_HOME' => bundler_install_dir],
|
165
|
+
env_for_child.merge('GEM_PATH' => nil, 'GEM_HOME' => bundler_install_dir),
|
103
166
|
gem_program, 'install', '--no-document', '--no-user-install', '--no-format-executable',
|
167
|
+
*local,
|
104
168
|
"--bindir=#{File.join(bundler_install_dir, 'bin')}", 'bundler')
|
105
169
|
|
106
170
|
if !result
|
107
171
|
STDERR.puts "FATAL: failed to install bundler in #{dot_autoproj}"
|
108
172
|
exit 1
|
109
173
|
end
|
174
|
+
env['GEM_PATH'] << bundler_install_dir
|
175
|
+
env['PATH'] << File.join(bundler_install_dir, 'bin')
|
110
176
|
File.join(bin_dir, 'bundler')
|
111
177
|
end
|
112
178
|
|
113
179
|
def save_env_sh
|
114
180
|
env = Autobuild::Environment.new
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
181
|
+
env.prepare
|
182
|
+
|
183
|
+
%w{GEM_HOME GEM_PATH}.each do |name|
|
184
|
+
value = self.env[name]
|
185
|
+
if value.empty?
|
186
|
+
env.unset name
|
187
|
+
else
|
188
|
+
env.set name, *value
|
189
|
+
end
|
119
190
|
end
|
120
191
|
env.push_path 'PATH', File.join(autoproj_install_dir, 'bin')
|
121
|
-
|
192
|
+
|
122
193
|
if private_autoproj?
|
123
194
|
env.push_path 'GEM_PATH', autoproj_install_dir
|
124
195
|
end
|
@@ -142,7 +213,9 @@ def save_gemfile
|
|
142
213
|
io.write gemfile
|
143
214
|
end
|
144
215
|
end
|
145
|
-
|
216
|
+
|
217
|
+
ENV_BUNDLE_GEMFILE_RX = /^(\s*ENV\[['"]BUNDLE_GEMFILE['"]\]\s*)(?:\|\|)?=/
|
218
|
+
|
146
219
|
def install_autoproj(bundler)
|
147
220
|
# Force bundler to update. If the user does not want this, let him specify a
|
148
221
|
# Gemfile with tighter version constraints
|
@@ -151,24 +224,57 @@ def install_autoproj(bundler)
|
|
151
224
|
FileUtils.rm lockfile
|
152
225
|
end
|
153
226
|
|
154
|
-
env = Hash['BUNDLE_GEMFILE' => nil, 'RUBYLIB' => nil]
|
155
227
|
opts = Array.new
|
228
|
+
opts << '--local' if local?
|
156
229
|
|
230
|
+
env = env_for_child
|
157
231
|
if private_autoproj?
|
158
|
-
env =
|
159
|
-
|
232
|
+
env = env.merge(
|
233
|
+
'GEM_PATH' => bundler_install_dir,
|
234
|
+
'GEM_HOME' => nil)
|
160
235
|
opts << "--clean" << "--path=#{autoproj_install_dir}"
|
161
236
|
end
|
162
237
|
|
238
|
+
binstubs_path = File.join(autoproj_install_dir, 'bin')
|
239
|
+
|
163
240
|
result = system(env,
|
164
|
-
bundler, 'install',
|
241
|
+
Gem.ruby, bundler, 'install',
|
165
242
|
"--gemfile=#{autoproj_gemfile_path}",
|
166
|
-
"--binstubs=#{
|
243
|
+
"--binstubs=#{binstubs_path}",
|
167
244
|
*opts)
|
168
245
|
if !result
|
169
246
|
STDERR.puts "FATAL: failed to install autoproj in #{dot_autoproj}"
|
170
247
|
exit 1
|
171
248
|
end
|
249
|
+
|
250
|
+
# Now tune the binstubs to force the usage of the autoproj
|
251
|
+
# gemfile. Otherwise, they get BUNDLE_GEMFILE from the
|
252
|
+
# environment by default
|
253
|
+
Dir.glob(File.join(binstubs_path, '*')) do |path|
|
254
|
+
next if !File.file?(path)
|
255
|
+
# Do NOT do that for bundler, otherwise it will fail with an
|
256
|
+
# "already loaded gemfile" message once we e.g. try to do
|
257
|
+
# 'bundler install --gemfile=NEW_GEMFILE'
|
258
|
+
next if File.basename(path) == 'bundler'
|
259
|
+
|
260
|
+
lines = File.readlines(path)
|
261
|
+
matched = false
|
262
|
+
filtered = lines.map do |l|
|
263
|
+
matched ||= (ENV_BUNDLE_GEMFILE_RX === l)
|
264
|
+
l.gsub(ENV_BUNDLE_GEMFILE_RX, '\\1=')
|
265
|
+
end
|
266
|
+
if !matched
|
267
|
+
raise UnexpectedBinstub, "expected #{path} to contain a line looking like ENV['BUNDLE_GEMFILE'] ||= but could not find one"
|
268
|
+
end
|
269
|
+
File.open(path, 'w') do |io|
|
270
|
+
io.write filtered.join("")
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
env['PATH'] << File.join(autoproj_install_dir, 'bin')
|
275
|
+
if private_autoproj?
|
276
|
+
env['GEM_PATH'] << autoproj_install_dir
|
277
|
+
end
|
172
278
|
end
|
173
279
|
|
174
280
|
def update_configuration
|
@@ -185,25 +291,92 @@ def update_configuration
|
|
185
291
|
end
|
186
292
|
end
|
187
293
|
|
294
|
+
def find_in_clean_path(command)
|
295
|
+
clean_path = env_for_child['PATH'].split(File::PATH_SEPARATOR)
|
296
|
+
clean_path.each do |p|
|
297
|
+
full_path = File.join(p, command)
|
298
|
+
if File.file?(full_path)
|
299
|
+
return full_path
|
300
|
+
end
|
301
|
+
end
|
302
|
+
nil
|
303
|
+
end
|
304
|
+
|
305
|
+
def find_bundler
|
306
|
+
clean_env = env_for_child
|
307
|
+
Gem.paths = Hash[
|
308
|
+
'GEM_HOME' => clean_env['GEM_HOME'] || Gem.default_dir,
|
309
|
+
'GEM_PATH' => clean_env['GEM_PATH'] || nil
|
310
|
+
]
|
311
|
+
# Here, we're getting into the esotheric
|
312
|
+
#
|
313
|
+
# The problem is that e.g. Ubuntu and Debian install an
|
314
|
+
# operating_system.rb file that sets proper OS defaults. Some
|
315
|
+
# autoproj installs have it in their RUBYLIB but should not
|
316
|
+
# because of limitations of autoproj 1.x. This leads to
|
317
|
+
# Gem.bindir being *not* valid for subprocesses
|
318
|
+
#
|
319
|
+
# So, we're calling 'gem' as a subcommand to discovery the
|
320
|
+
# actual bindir
|
321
|
+
bindir = IO.popen(clean_env, [Gem.ruby, '-e', 'puts Gem.bindir']).read
|
322
|
+
if bindir
|
323
|
+
env['PATH'].unshift bindir.chomp
|
324
|
+
else
|
325
|
+
STDERR.puts "FATAL: cannot run #{Gem.ruby} -e 'puts Gem.bindir'"
|
326
|
+
exit 1
|
327
|
+
end
|
328
|
+
|
329
|
+
bundler = find_in_clean_path('bundler')
|
330
|
+
if !bundler
|
331
|
+
clean_path = env_for_child['PATH']
|
332
|
+
STDERR.puts "FATAL: cannot find 'bundler' in PATH=#{clean_path}"
|
333
|
+
if ENV['PATH'] != clean_path
|
334
|
+
STDERR.puts " it appears that you already have some autoproj-generated env.sh loaded"
|
335
|
+
STDERR.puts " - if you are running 'autoproj upgrade', please contact the autoproj author at https://github.com/rock-core/autoproj/issues/new"
|
336
|
+
STDERR.puts " - if you are running an install, try again in a console where the env.sh is not loaded"
|
337
|
+
exit 1
|
338
|
+
else
|
339
|
+
STDERR.puts " the recommended action is to install it manually first by running 'gem install bundler'"
|
340
|
+
STDERR.puts " or call this command again with --private-bundler to have it installed in the workspace"
|
341
|
+
exit 1
|
342
|
+
end
|
343
|
+
end
|
344
|
+
bundler
|
345
|
+
end
|
346
|
+
|
188
347
|
def install
|
189
348
|
if private_bundler?
|
190
349
|
puts "Installing bundler in #{bundler_install_dir}"
|
191
350
|
bundler = install_bundler
|
351
|
+
else
|
352
|
+
bundler = find_bundler
|
353
|
+
puts "Detected bundler at #{bundler}"
|
192
354
|
end
|
193
355
|
save_gemfile
|
194
356
|
puts "Installing autoproj in #{dot_autoproj}"
|
195
|
-
install_autoproj(bundler
|
357
|
+
install_autoproj(bundler)
|
196
358
|
end
|
197
359
|
|
198
360
|
# Actually perform the install
|
199
|
-
def run
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
361
|
+
def run(stage2: false)
|
362
|
+
if stage2
|
363
|
+
require 'autobuild'
|
364
|
+
save_env_sh
|
365
|
+
else
|
366
|
+
install
|
367
|
+
|
368
|
+
env_for_child.each do |k, v|
|
369
|
+
if v
|
370
|
+
ENV[k] = v
|
371
|
+
else
|
372
|
+
ENV.delete(k)
|
373
|
+
end
|
374
|
+
end
|
375
|
+
ENV['BUNDLE_GEMFILE'] = autoproj_gemfile_path
|
376
|
+
update_configuration
|
377
|
+
exec Gem.ruby, File.join(autoproj_install_dir, 'bin', 'autoproj'),
|
378
|
+
'install-stage2', root_dir
|
379
|
+
end
|
207
380
|
end
|
208
381
|
end
|
209
382
|
end
|