autoproj 2.0.0.rc4 → 2.0.0.rc5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|