autoproj 2.0.0.b5 → 2.0.0.b6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cfa3cb994d982b9d14f2a88e2b45959e42a12065
4
- data.tar.gz: 041609d6fbe3a41b52e8d78992311bbfea212f71
3
+ metadata.gz: 7ac674274886714c8971929bc69953eb9a8554de
4
+ data.tar.gz: 1722b19143830e552aad26239225e742dd6bda78
5
5
  SHA512:
6
- metadata.gz: 748d75cb0dfa737f899f84a6519e25b84125dee8dae9f1ddd9fb768f3c7100ed599ccb3c7fa59657ad78dc4e2186d9e575735ec9535cf8fd79900e106a8a7177
7
- data.tar.gz: b221afdac5fbba3958b71aaec7e7c88bc1100ac5d58768d76bf98077e6a00e418786dbb6fa7d5ea7d90c118d1870625ad8e5f21b81b599392bdc6c71dcad4cd3
6
+ metadata.gz: 13148336716af711440e24212d70f83330ec82336ddb77cad4c32cb9d487a27f1180b523628a0dfd5812b45221bb1a805a679a55bcf0360cda969c2036f6d9a4
7
+ data.tar.gz: 6a487132bf1e90c569cb534e01706627c942d1bdf58b689786fc440c836fd2a3ecdf76d2c9cc85d58ee8e02dd8e7ac1c6b0718629d9090037f0e243437465fe2
data/Rakefile CHANGED
@@ -5,15 +5,15 @@ task 'default'
5
5
  Utilrb::Rake.hoe do
6
6
  namespace 'dist' do
7
7
  Hoe.spec 'autoproj' do
8
- self.developer "Rock Core Developers", "rock-dev@dfki.de"
8
+ self.developer "Sylvain Joyeux", "sylvain.joyeux@m4x.org"
9
9
 
10
10
  self.urls = ["http://rock-robotics.org/documentation/autoproj"]
11
11
  self.group_name = 'autobuild'
12
12
  self.summary = 'Easy installation and management of sets of software packages'
13
13
  self.description = "autoproj is a manager for sets of software packages. It allows the user to import and build packages from source, still using the underlying distribution's native package manager for software that is available on it."
14
- self.email = "rock-dev@dfki.de"
14
+ self.email = "sylvain.joyeux@m4x.org"
15
15
 
16
- self.spec_extras[:required_ruby_version] = ">= 1.9.2"
16
+ self.spec_extras[:required_ruby_version] = ">= 1.9.3"
17
17
 
18
18
  license 'BSD'
19
19
 
@@ -21,7 +21,8 @@ Utilrb::Rake.hoe do
21
21
  ['autobuild', '~> 1.9', '>= 1.9.0'] <<
22
22
  ['utilrb', '~> 2.0', '>= 2.0.0'] <<
23
23
  ['highline', '~> 1.7', '>= 1.7.0'] <<
24
- ['thor', '~> 0.19.0', '>= 0.19.1']
24
+ ['thor', '~> 0.19.0', '>= 0.19.1'] <<
25
+ ['concurrent-ruby']
25
26
  end
26
27
  end
27
28
  end
@@ -385,6 +385,14 @@ module Autoproj
385
385
  set('import_log_enabled', !!value)
386
386
  end
387
387
 
388
+ def parallel_import_level
389
+ get('parallel_import_level', 10)
390
+ end
391
+
392
+ def parallel_import_level=(level)
393
+ set('parallel_import_level', level)
394
+ end
395
+
388
396
  def ruby_executable
389
397
  if path = get('ruby_executable', nil)
390
398
  path
data/lib/autoproj.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "enumerator"
2
2
  require 'utilrb/module/attr_predicate'
3
+ require 'concurrent'
3
4
  require 'autobuild'
4
5
  require 'autoproj/base'
5
6
  require 'autoproj/exceptions'
@@ -127,7 +127,8 @@ module Autoproj
127
127
  verbose: false,
128
128
  debug: false,
129
129
  color: true,
130
- progress: true
130
+ progress: true,
131
+ parallel: nil
131
132
 
132
133
  Autoproj.silent = options[:silent]
133
134
  if options[:verbose]
@@ -145,6 +146,10 @@ module Autoproj
145
146
  end
146
147
 
147
148
  Autobuild.color = options[:color]
149
+ if level = options[:parallel]
150
+ Autobuild.parallel_build_level = Integer(level)
151
+ remaining[:parallel] = Integer(level)
152
+ end
148
153
 
149
154
  Autobuild.progress_display_enabled = options[:progress]
150
155
  return args, remaining
@@ -25,7 +25,9 @@ module Autoproj
25
25
  Autobuild.ignore_errors = options[:keep_going]
26
26
 
27
27
  command_line_selection, source_packages, osdep_packages =
28
- super(selected_packages, options.merge(checkout_only: true, apply_post_install: false))
28
+ super(selected_packages, options.merge(checkout_only: true))
29
+
30
+ return if source_packages.empty?
29
31
 
30
32
  # Disable all packages that are not selected
31
33
  ws.manifest.each_autobuild_package do |pkg|
@@ -70,7 +72,6 @@ module Autoproj
70
72
  Autobuild.do_build = true
71
73
  ops.build_packages(source_packages)
72
74
  Autobuild.apply(source_packages, "autoproj-build", ['install'])
73
- ws.apply_post_install
74
75
  end
75
76
  end
76
77
  end
@@ -12,7 +12,7 @@ module Autoproj
12
12
  Autoproj.silent do
13
13
  ws.setup
14
14
  if mainline = options[:mainline]
15
- if mainline == 'true'
15
+ if mainline == 'mainline' || mainline == 'true'
16
16
  mainline = true
17
17
  end
18
18
  end
@@ -48,7 +48,6 @@ module Autoproj
48
48
  source_packages, osdep_packages, resolved_selection =
49
49
  resolve_selection(ws.manifest, packages, options)
50
50
  ws.finalize_setup
51
- ws.apply_post_install
52
51
  ws.export_installation_manifest
53
52
  return source_packages, osdep_packages, resolved_selection, config_selected
54
53
  end
@@ -93,6 +93,17 @@ module Autoproj
93
93
  desc: 'controls whether the osdeps subsystem should filter up-to-date packages or not', default: true
94
94
  option :deps, default: true, type: :boolean,
95
95
  desc: 'whether the package dependencies should be recursively updated (the default) or not'
96
+ option :reset, default: false, type: :boolean,
97
+ desc: "forcefully resets the repository to the state expected by autoproj's configuration",
98
+ long_desc: "The default is to update the repository if possible, and leave it alone otherwise. With --reset, autoproj update might come back to an older commit than the repository's current state"
99
+ option :force_reset, default: false, type: :boolean,
100
+ desc: "like --reset, but bypasses tests that ensure you won't lose data"
101
+ option :retry_count, default: nil, type: :numeric,
102
+ desc: "force the importer's retry count to this value"
103
+ option :parallel, aliases: :p, type: :numeric,
104
+ desc: 'maximum number of parallel jobs'
105
+ option :mainline, type: :string,
106
+ 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"
96
107
  def update(*packages)
97
108
  run_autoproj_cli(:update, :Update, Hash[silent: false], *packages)
98
109
  end
@@ -112,6 +123,8 @@ module Autoproj
112
123
  desc: 'controls whether missing osdeps should be installed. In rebuild mode, also controls whether the osdeps should be reinstalled or not (the default is to reinstall them)'
113
124
  option :deps, type: :boolean,
114
125
  desc: 'in force or rebuild modes, control whether the force/rebuild action should apply only on the packages given on the command line, or on their dependencies as well (the default is --no-deps)'
126
+ option :parallel, aliases: :p, type: :numeric,
127
+ desc: 'maximum number of parallel jobs'
115
128
  def build(*packages)
116
129
  run_autoproj_cli(:build, :Build, Hash[silent: false], *packages)
117
130
  end
@@ -164,10 +177,19 @@ module Autoproj
164
177
  end
165
178
 
166
179
  desc 'versions [PACKAGES]', 'generate a version file for the given packages, or all packages if none are given'
167
- option :package_sets, type: :boolean,
180
+ option :config, type: :boolean,
168
181
  default: nil,
169
182
  banner: '',
170
- desc: 'controls whether the package sets should be versioned as well. This is the default if no packages are given on the command line or if the autoproj directory is'
183
+ desc: "controls whether the package sets should be versioned as well",
184
+ long_desc: <<-EOD
185
+ This is the default if no packages are given on the command line, or if the
186
+ autoproj main configuration directory is. Note that if --config but no packages
187
+ are given, the packages will not be versioned. In other words,
188
+ autoproj versions # versions everything, configuration and packages
189
+ autoproj versions --config # versions only the configuration
190
+ autoproj versions autoproj/ # versions only the configuration
191
+ autoproj versions autoproj a/package # versions the configuration and the specified package(s)
192
+ EOD
171
193
  option :keep_going, aliases: :k, type: :boolean,
172
194
  default: false,
173
195
  banner: '',
@@ -223,32 +245,36 @@ module Autoproj
223
245
  run_autoproj_cli(:switch_config, :SwitchConfig, Hash[], *args)
224
246
  end
225
247
 
226
- desc 'query <query string>', 'searches for packages matching a query string'
248
+ desc 'query [QUERY]', 'searches for packages matching a query string. With no query string, matches all packages.'
227
249
  long_desc <<-EOD
228
250
  Finds packages that match query_string and displays information about them (one per line)
229
251
  By default, only the package name is displayed. It can be customized with the --format option
230
252
 
231
253
  QUERY KEYS
232
- autobuild.name: the package name
233
- autobuild.srcdir: the package source directory
234
- autobuild.class.name: the package class
235
- vcs.type: the VCS type (as used in the source.yml files)
236
- vcs.url: the URL from the VCS. The exact semantic of it depends on the VCS type
254
+
255
+ autobuild.name: the package name,
256
+ autobuild.srcdir: the package source directory,
257
+ autobuild.class.name: the package class,
258
+ vcs.type: the VCS type (as used in the source.yml files),
259
+ vcs.url: the URL from the VCS,
237
260
  package_set.name: the name of the package set that defines the package
238
261
 
239
262
  FORMAT SPECIFICATION
240
263
 
241
264
  The format is a string in which special values can be expanded using a $VARNAME format. The following variables are accepted:
242
- NAME: the package name
243
- SRCDIR: the full path to the package source directory
265
+
266
+ NAME: the package name,
267
+
268
+ SRCDIR: the full path to the package source directory,
269
+
244
270
  PREFIX: the full path to the package installation directory
245
271
  EOD
246
272
  option :search_all, type: :boolean,
247
273
  desc: 'search in all defined packages instead of only in those selected selected in the layout'
248
274
  option :format, type: :string,
249
275
  desc: "customize what should be displayed. See FORMAT SPECIFICATION above"
250
- def query(query_string)
251
- run_autoproj_cli(:query, :Query, Hash[], query_string)
276
+ def query(query_string = nil)
277
+ run_autoproj_cli(:query, :Query, Hash[], *Array(query_string))
252
278
  end
253
279
  end
254
280
  end
@@ -6,32 +6,55 @@ module Autoproj
6
6
  class Query < InspectionTool
7
7
  def run(query_string, options = Hash.new)
8
8
  initialize_and_load
9
- finalize_setup([])
10
- query = Autoproj::Query.parse_query(query_string.first)
11
-
12
- packages =
13
- if options[:search_all]
14
- ws.manifest.packages.to_a
15
- else
16
- ws.manifest.all_selected_packages.map do |pkg_name|
17
- [pkg_name, ws.manifest.packages[pkg_name]]
18
- end
9
+ all_selected_packages, * =
10
+ finalize_setup([], ignore_non_imported_packages: true)
11
+ all_selected_packages = all_selected_packages.to_set
12
+
13
+ query =
14
+ if !query_string.empty?
15
+ Autoproj::Query.parse_query(query_string.first)
19
16
  end
20
17
 
21
- matches = packages.map do |name, pkg_def|
22
- if priority = query.match(pkg_def)
23
- [priority, name]
18
+ if options[:search_all]
19
+ packages = ws.manifest.packages.to_a
20
+ else
21
+ packages = all_selected_packages.map do |pkg_name|
22
+ [pkg_name, ws.manifest.find_package(pkg_name)]
23
+ end
24
+ packages += ws.manifest.all_selected_packages.map do |pkg_name|
25
+ if !all_selected_packages.include?(pkg_name)
26
+ [pkg_name, ws.manifest.find_package(pkg_name)]
27
+ end
28
+ end.compact
29
+ end
30
+
31
+ if options[:only_present]
32
+ packages = packages.find_all do |_, pkg|
33
+ File.directory?(pkg.autobuild.srcdir)
24
34
  end
25
- end.compact
35
+ end
36
+
37
+ if !query
38
+ matches = packages.map { |name, _| [0, name] }
39
+ else
40
+ matches = packages.map do |name, pkg_def|
41
+ if priority = query.match(pkg_def)
42
+ [priority, name]
43
+ end
44
+ end.compact
45
+ end
26
46
 
27
47
  fields = Hash.new
28
48
  matches = matches.sort
29
49
  matches.each do |priority, name|
50
+ pkg_def = ws.manifest.find_package(name)
30
51
  pkg = ws.manifest.find_autobuild_package(name)
31
52
  fields['SRCDIR'] = pkg.srcdir
32
53
  fields['PREFIX'] = pkg.prefix
33
54
  fields['NAME'] = name
34
55
  fields['PRIORITY'] = priority
56
+ fields['URL'] = (pkg_def.vcs.url if pkg_def.vcs)
57
+ fields['PRESENT'] = File.directory?(pkg.srcdir)
35
58
 
36
59
  value = Autoproj.expand(options[:format] || "$NAME", fields)
37
60
  puts value
@@ -43,81 +43,99 @@ module Autoproj
43
43
  display_status(packages, only_local: options[:only_local])
44
44
  end
45
45
 
46
+ PackageStatus = Struct.new :msg, :sync, :uncommitted, :local, :remote
47
+ def status_of_package(pkg, options = Hash.new)
48
+ package_status = PackageStatus.new(Array.new, false, false, false, false)
49
+ if !pkg.importer
50
+ package_status.msg << Autoproj.color(" is a local-only package (no VCS)", :bold, :red)
51
+ elsif !pkg.importer.respond_to?(:status)
52
+ package_status.msg << Autoproj.color(" the #{pkg.importer.class.name.gsub(/.*::/, '')} importer does not support status display", :bold, :red)
53
+ elsif !File.directory?(pkg.srcdir)
54
+ package_status.msg << Autoproj.color(" is not imported yet", :magenta)
55
+ else
56
+ begin status = pkg.importer.status(pkg, options[:only_local])
57
+ rescue Interrupt
58
+ raise
59
+ rescue Exception => e
60
+ package_status.msg << Autoproj.color(" failed to fetch status information (#{e})", :red)
61
+ return package_status
62
+ end
63
+
64
+ if status.uncommitted_code
65
+ package_status.msg << Autoproj.color(" contains uncommitted modifications", :red)
66
+ package_status.uncommitted = true
67
+ end
68
+
69
+ case status.status
70
+ when Autobuild::Importer::Status::UP_TO_DATE
71
+ package_status.sync = true
72
+ when Autobuild::Importer::Status::ADVANCED
73
+ package_status.local = true
74
+ package_status.msg << Autoproj.color(" local contains #{status.local_commits.size} commit that remote does not have:", :blue)
75
+ status.local_commits.each do |line|
76
+ package_status.msg << Autoproj.color(" #{line}", :blue)
77
+ end
78
+ when Autobuild::Importer::Status::SIMPLE_UPDATE
79
+ package_status.remote = true
80
+ package_status.msg << Autoproj.color(" remote contains #{status.remote_commits.size} commit that local does not have:", :magenta)
81
+ status.remote_commits.each do |line|
82
+ package_status.msg << Autoproj.color(" #{line}", :magenta)
83
+ end
84
+ when Autobuild::Importer::Status::NEEDS_MERGE
85
+ package_status.local = true
86
+ package_status.remote = true
87
+ package_status.msg << " local and remote have diverged with respectively #{status.local_commits.size} and #{status.remote_commits.size} commits each"
88
+ package_status.msg << Autoproj.color(" -- local commits --", :blue)
89
+ status.local_commits.each do |line|
90
+ package_status.msg << Autoproj.color(" #{line}", :blue)
91
+ end
92
+ package_status.msg << Autoproj.color(" -- remote commits --", :magenta)
93
+ status.remote_commits.each do |line|
94
+ package_status.msg << Autoproj.color(" #{line}", :magenta)
95
+ end
96
+ end
97
+ end
98
+ package_status
99
+ end
100
+
46
101
  StatusResult = Struct.new :uncommitted, :local, :remote
47
102
  def display_status(packages, options = Hash.new)
48
103
  result = StatusResult.new
49
104
 
105
+ executor = Concurrent::FixedThreadPool.new(ws.config.parallel_import_level, max_length: 0)
106
+ interactive, noninteractive = packages.partition { |pkg| pkg.importer && pkg.importer.interactive? }
107
+ noninteractive = noninteractive.map do |pkg|
108
+ [pkg, Concurrent::Future.execute(executor: executor) { status_of_package(pkg, only_local: options[:only_local]) }]
109
+ end
110
+
50
111
  sync_packages = ""
51
- packages.each do |pkg|
52
- lines = []
112
+ (noninteractive + interactive).each do |pkg, future|
113
+ if future
114
+ if error = future.reason
115
+ raise error
116
+ end
117
+ status = future.value
118
+ else status = status_of_package(pkg, only_local: options[:only_local])
119
+ end
53
120
 
54
- pkg_name = pkg.autoproj_name
121
+ result.uncommitted ||= status.uncommitted
122
+ result.local ||= status.local
123
+ result.remote ||= status.remote
55
124
 
56
- if !pkg.importer
57
- lines << Autoproj.color(" is a local-only package (no VCS)", :bold, :red)
58
- elsif !pkg.importer.respond_to?(:status)
59
- lines << Autoproj.color(" the #{pkg.importer.class.name.gsub(/.*::/, '')} importer does not support status display", :bold, :red)
60
- elsif !File.directory?(pkg.srcdir)
61
- lines << Autoproj.color(" is not imported yet", :magenta)
62
- else
63
- status = begin pkg.importer.status(pkg, options[:only_local])
64
- rescue Interrupt
65
- raise
66
- rescue Exception => e
67
- lines << Autoproj.color(" failed to fetch status information (#{e})", :red)
68
- nil
69
- end
70
-
71
- if status
72
- if status.uncommitted_code
73
- lines << Autoproj.color(" contains uncommitted modifications", :red)
74
- result.uncommitted = true
75
- end
76
-
77
- case status.status
78
- when Autobuild::Importer::Status::UP_TO_DATE
79
- if !status.uncommitted_code
80
- if sync_packages.size > 80
81
- Autoproj.message "#{sync_packages},"
82
- sync_packages = ""
83
- end
84
- msg = if sync_packages.empty?
85
- pkg_name
86
- else
87
- ", #{pkg_name}"
88
- end
89
- STDERR.print msg
90
- sync_packages = "#{sync_packages}#{msg}"
91
- next
92
- else
93
- lines << Autoproj.color(" local and remote are in sync", :green)
94
- end
95
- when Autobuild::Importer::Status::ADVANCED
96
- result.local = true
97
- lines << Autoproj.color(" local contains #{status.local_commits.size} commit that remote does not have:", :blue)
98
- status.local_commits.each do |line|
99
- lines << Autoproj.color(" #{line}", :blue)
100
- end
101
- when Autobuild::Importer::Status::SIMPLE_UPDATE
102
- result.remote = true
103
- lines << Autoproj.color(" remote contains #{status.remote_commits.size} commit that local does not have:", :magenta)
104
- status.remote_commits.each do |line|
105
- lines << Autoproj.color(" #{line}", :magenta)
106
- end
107
- when Autobuild::Importer::Status::NEEDS_MERGE
108
- result.local = true
109
- result.remote = true
110
- lines << " local and remote have diverged with respectively #{status.local_commits.size} and #{status.remote_commits.size} commits each"
111
- lines << Autoproj.color(" -- local commits --", :blue)
112
- status.local_commits.each do |line|
113
- lines << Autoproj.color(" #{line}", :blue)
114
- end
115
- lines << Autoproj.color(" -- remote commits --", :magenta)
116
- status.remote_commits.each do |line|
117
- lines << Autoproj.color(" #{line}", :magenta)
118
- end
119
- end
125
+ pkg_name = pkg.autoproj_name
126
+ if status.sync && status.msg.empty?
127
+ if sync_packages.size > 80
128
+ Autoproj.message "#{sync_packages},"
129
+ sync_packages = ""
120
130
  end
131
+ msg = if sync_packages.empty?
132
+ pkg_name
133
+ else
134
+ ", #{pkg_name}"
135
+ end
136
+ STDERR.print msg
137
+ sync_packages = "#{sync_packages}#{msg}"
138
+ next
121
139
  end
122
140
 
123
141
  if !sync_packages.empty?
@@ -127,20 +145,28 @@ module Autoproj
127
145
 
128
146
  STDERR.print
129
147
 
130
- if lines.size == 1
131
- Autoproj.message "#{pkg_name}: #{lines.first}"
148
+ if status.msg.size == 1
149
+ Autoproj.message "#{pkg_name}: #{status.msg.first}"
132
150
  else
133
151
  Autoproj.message "#{pkg_name}:"
134
- lines.each do |l|
152
+ status.msg.each do |l|
135
153
  Autoproj.message l
136
154
  end
137
155
  end
138
156
  end
139
157
  if !sync_packages.empty?
140
158
  Autoproj.message("#{sync_packages}: #{Autoproj.color("local and remote are in sync", :green)}")
141
- sync_packages = ""
142
159
  end
143
160
  return result
161
+
162
+ rescue Interrupt
163
+ Autoproj.warn "Interrupted, waiting for pending jobs to finish"
164
+ rescue Exception => e
165
+ Autoproj.error "internal error: #{e}, waiting for pending jobs to finish"
166
+ raise
167
+ ensure
168
+ executor.shutdown
169
+ executor.wait_for_termination
144
170
  end
145
171
 
146
172
  end