autobuild 1.7.10 → 1.7.11.rc1
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.
- data/Manifest.txt +3 -0
- data/lib/autobuild.rb +37 -7
- data/lib/autobuild/config.rb +85 -13
- data/lib/autobuild/configurable.rb +0 -7
- data/lib/autobuild/environment.rb +2 -3
- data/lib/autobuild/import/archive.rb +34 -4
- data/lib/autobuild/import/cvs.rb +5 -5
- data/lib/autobuild/import/darcs.rb +5 -1
- data/lib/autobuild/import/git.rb +211 -65
- data/lib/autobuild/import/hg.rb +5 -1
- data/lib/autobuild/import/svn.rb +5 -1
- data/lib/autobuild/importer.rb +5 -5
- data/lib/autobuild/package.rb +70 -131
- data/lib/autobuild/packages/autotools.rb +32 -13
- data/lib/autobuild/packages/cmake.rb +30 -16
- data/lib/autobuild/packages/dummy.rb +1 -1
- data/lib/autobuild/packages/genom.rb +1 -1
- data/lib/autobuild/packages/orogen.rb +1 -1
- data/lib/autobuild/packages/ruby.rb +109 -0
- data/lib/autobuild/parallel.rb +56 -17
- data/lib/autobuild/rake_task_extension.rb +19 -0
- data/lib/autobuild/reporting.rb +5 -20
- data/lib/autobuild/subcommand.rb +6 -6
- data/lib/autobuild/timestamps.rb +2 -7
- data/lib/autobuild/utility.rb +164 -0
- data/lib/autobuild/version.rb +1 -1
- data/test/test_config.rb +83 -0
- metadata +16 -11
data/Manifest.txt
CHANGED
|
@@ -27,12 +27,15 @@ lib/autobuild/packages/gnumake.rb
|
|
|
27
27
|
lib/autobuild/packages/import.rb
|
|
28
28
|
lib/autobuild/packages/orogen.rb
|
|
29
29
|
lib/autobuild/packages/pkgconfig.rb
|
|
30
|
+
lib/autobuild/packages/ruby.rb
|
|
31
|
+
lib/autobuild/utility.rb
|
|
30
32
|
lib/autobuild/parallel.rb
|
|
31
33
|
lib/autobuild/pkgconfig.rb
|
|
32
34
|
lib/autobuild/reporting.rb
|
|
33
35
|
lib/autobuild/subcommand.rb
|
|
34
36
|
lib/autobuild/timestamps.rb
|
|
35
37
|
lib/autobuild/version.rb
|
|
38
|
+
lib/autobuild/rake_task_extension.rb
|
|
36
39
|
samples/openrobots.autobuild
|
|
37
40
|
test/data/cvsroot.tar
|
|
38
41
|
test/data/svnroot.tar
|
data/lib/autobuild.rb
CHANGED
|
@@ -4,11 +4,40 @@ if defined? Rake::DSL
|
|
|
4
4
|
include Rake::DSL
|
|
5
5
|
end
|
|
6
6
|
|
|
7
|
+
module Autobuild
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
begin
|
|
11
|
+
require 'rmail'
|
|
12
|
+
require 'rmail/serialize'
|
|
13
|
+
Autobuild::HAS_RMAIL = true
|
|
14
|
+
rescue LoadError
|
|
15
|
+
Autobuild::HAS_RMAIL = false
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
require 'net/smtp'
|
|
19
|
+
require 'socket'
|
|
20
|
+
require 'etc'
|
|
21
|
+
require 'find'
|
|
22
|
+
require 'thread'
|
|
23
|
+
require 'pathname'
|
|
24
|
+
require 'shellwords'
|
|
25
|
+
require 'find'
|
|
26
|
+
require 'rake/tasklib'
|
|
27
|
+
require 'fileutils'
|
|
28
|
+
|
|
7
29
|
require 'autobuild/version'
|
|
8
|
-
require 'autobuild/config'
|
|
9
|
-
require 'autobuild/configurable'
|
|
10
30
|
require 'autobuild/environment'
|
|
11
31
|
require 'autobuild/exceptions'
|
|
32
|
+
require 'autobuild/pkgconfig'
|
|
33
|
+
require 'autobuild/reporting'
|
|
34
|
+
require 'autobuild/subcommand'
|
|
35
|
+
require 'autobuild/timestamps'
|
|
36
|
+
require 'autobuild/parallel'
|
|
37
|
+
require 'autobuild/utility'
|
|
38
|
+
require 'autobuild/config'
|
|
39
|
+
|
|
40
|
+
require 'autobuild/importer'
|
|
12
41
|
require 'autobuild/import/cvs'
|
|
13
42
|
require 'autobuild/import/darcs'
|
|
14
43
|
require 'autobuild/importer'
|
|
@@ -17,6 +46,9 @@ require 'autobuild/import/hg'
|
|
|
17
46
|
require 'autobuild/import/svn'
|
|
18
47
|
require 'autobuild/import/archive'
|
|
19
48
|
require 'autobuild/import/tar'
|
|
49
|
+
|
|
50
|
+
require 'autobuild/package'
|
|
51
|
+
require 'autobuild/configurable'
|
|
20
52
|
require 'autobuild/packages/autotools'
|
|
21
53
|
require 'autobuild/packages/cmake'
|
|
22
54
|
require 'autobuild/packages/genom'
|
|
@@ -24,9 +56,7 @@ require 'autobuild/packages/import'
|
|
|
24
56
|
require 'autobuild/packages/orogen'
|
|
25
57
|
require 'autobuild/packages/pkgconfig'
|
|
26
58
|
require 'autobuild/packages/dummy'
|
|
27
|
-
require 'autobuild/
|
|
28
|
-
|
|
29
|
-
require 'autobuild/
|
|
30
|
-
require 'autobuild/timestamps'
|
|
31
|
-
require 'autobuild/parallel'
|
|
59
|
+
require 'autobuild/packages/ruby'
|
|
60
|
+
|
|
61
|
+
require 'autobuild/rake_task_extension'
|
|
32
62
|
|
data/lib/autobuild/config.rb
CHANGED
|
@@ -33,14 +33,47 @@ end
|
|
|
33
33
|
module Autobuild
|
|
34
34
|
class << self
|
|
35
35
|
%w{ nice srcdir prefix
|
|
36
|
-
verbose debug do_update do_build do_rebuild do_forced_build
|
|
36
|
+
verbose debug do_update do_build do_rebuild do_forced_build
|
|
37
37
|
daemonize clean_log packages default_packages
|
|
38
|
-
|
|
38
|
+
keep_oldlogs}.each do |name|
|
|
39
39
|
attr_accessor name
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
+
# @return [{String=>Class<Utility>}] the known utilities
|
|
43
|
+
# @see {register_utility_class}
|
|
44
|
+
attr_reader :utilities
|
|
45
|
+
|
|
46
|
+
def register_utility_class(name, klass)
|
|
47
|
+
utilities[name] = klass
|
|
48
|
+
singleton_class.class_eval do
|
|
49
|
+
attr_accessor "only_#{name}"
|
|
50
|
+
attr_accessor "do_#{name}"
|
|
51
|
+
attr_accessor "#{name}_prefix"
|
|
52
|
+
attr_accessor "pass_#{name}_errors"
|
|
53
|
+
end
|
|
54
|
+
instance_variable_set "@only_#{name}", false
|
|
55
|
+
instance_variable_set "@do_#{name}", false
|
|
56
|
+
instance_variable_set "@pass_#{name}_errors", false
|
|
57
|
+
instance_variable_set "@#{name}_prefix", name
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def create_utility(utility_name, package)
|
|
61
|
+
if klass = utilities[utility_name]
|
|
62
|
+
package.utilities[utility_name] = klass.new(utility_name, package)
|
|
63
|
+
else raise ArgumentError, "there is no utility called #{utility_name}, available utilities are #{utilities.keys.sort.join(", ")}"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
42
67
|
# Configure the programs used by different packages
|
|
43
68
|
attr_reader :programs
|
|
69
|
+
# A cache of entries in programs to their resolved full path
|
|
70
|
+
#
|
|
71
|
+
# @return [{String=>[String,String,String]}] the triplet (full path,
|
|
72
|
+
# tool name, value of ENV['PATH']). The last two values are used to
|
|
73
|
+
# invalidate the cache when needed
|
|
74
|
+
#
|
|
75
|
+
# @see tool_in_path
|
|
76
|
+
attr_reader :programs_in_path
|
|
44
77
|
# The directory in which logs are saved. Defaults to PREFIX/log.
|
|
45
78
|
attr_writer :logdir
|
|
46
79
|
|
|
@@ -52,6 +85,9 @@ module Autobuild
|
|
|
52
85
|
do_build && !only_doc && packages.empty?
|
|
53
86
|
end
|
|
54
87
|
end
|
|
88
|
+
@utilities = Hash.new
|
|
89
|
+
register_utility_class 'doc', Utility
|
|
90
|
+
register_utility_class 'test', Utility
|
|
55
91
|
|
|
56
92
|
@console = HighLine.new
|
|
57
93
|
|
|
@@ -74,11 +110,10 @@ module Autobuild
|
|
|
74
110
|
DEFAULT_OPTIONS = { :nice => nil,
|
|
75
111
|
:srcdir => Dir.pwd, :prefix => Dir.pwd, :logdir => nil,
|
|
76
112
|
:verbose => false, :debug => false, :do_build => true, :do_forced_build => false, :do_rebuild => false, :do_update => true,
|
|
77
|
-
:daemonize => false, :packages => [], :default_packages => [],
|
|
78
|
-
:only_doc => false, :do_doc => true, :doc_errors => false,
|
|
79
|
-
:doc_prefix => 'doc', :keep_oldlogs => false }
|
|
113
|
+
:daemonize => false, :packages => [], :default_packages => [], :keep_oldlogs => false }
|
|
80
114
|
|
|
81
115
|
@programs = Hash.new
|
|
116
|
+
@programs_in_path = Hash.new
|
|
82
117
|
DEFAULT_OPTIONS.each do |name, value|
|
|
83
118
|
send("#{name}=", value)
|
|
84
119
|
end
|
|
@@ -167,6 +202,40 @@ module Autobuild
|
|
|
167
202
|
programs[name.to_sym] || programs[name.to_s] || name.to_s
|
|
168
203
|
end
|
|
169
204
|
|
|
205
|
+
# Resolves the absolute path to a given tool
|
|
206
|
+
def tool_in_path(name)
|
|
207
|
+
path, path_name, path_env = programs_in_path[name]
|
|
208
|
+
current = tool(name)
|
|
209
|
+
if path_env != ENV['PATH'] || path_name != current
|
|
210
|
+
# Delete the current entry given that it is invalid
|
|
211
|
+
programs_in_path.delete(name)
|
|
212
|
+
if current[0, 1] == "/"
|
|
213
|
+
# This is already a full path
|
|
214
|
+
path = current
|
|
215
|
+
else
|
|
216
|
+
path = ENV['PATH'].split(':').
|
|
217
|
+
find { |dir| File.exists?(File.join(dir, current)) }
|
|
218
|
+
if path
|
|
219
|
+
path = File.join(path, current)
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
if !path
|
|
224
|
+
raise ArgumentError, "tool #{name}, set to #{current}, can not be found in PATH=#{path_env}"
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# Verify that the new value is a file and is executable
|
|
228
|
+
if !File.file?(path)
|
|
229
|
+
raise ArgumentError, "tool #{name} is set to #{current}, but this resolves to #{path} which is not a file"
|
|
230
|
+
elsif !File.executable?(path)
|
|
231
|
+
raise ArgumentError, "tool #{name} is set to #{current}, but this resolves to #{path} which is not executable"
|
|
232
|
+
end
|
|
233
|
+
programs_in_path[name] = [path, current, ENV['PATH']]
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
return path
|
|
237
|
+
end
|
|
238
|
+
|
|
170
239
|
# Gets autobuild options from the command line and returns the
|
|
171
240
|
# remaining elements
|
|
172
241
|
def commandline(args)
|
|
@@ -192,7 +261,7 @@ module Autobuild
|
|
|
192
261
|
opts.on("--rebuild", "clean and rebuild") do |v| Autobuild.do_forced_build = v end
|
|
193
262
|
opts.on("--only-doc", "only generate documentation") do |v| Autobuild.only_doc = v end
|
|
194
263
|
opts.on("--no-doc", "don't generate documentation") do |v| Autobuild.do_doc = v end
|
|
195
|
-
opts.on("--doc-errors", "treat documentation failure as error") do |v| Autobuild.
|
|
264
|
+
opts.on("--doc-errors", "treat documentation failure as error") do |v| Autobuild.pass_doc_errors = v end
|
|
196
265
|
|
|
197
266
|
opts.separator ""
|
|
198
267
|
opts.separator "Program output"
|
|
@@ -239,7 +308,7 @@ module Autobuild
|
|
|
239
308
|
end
|
|
240
309
|
end
|
|
241
310
|
|
|
242
|
-
def self.apply(packages, buildname = "autobuild")
|
|
311
|
+
def self.apply(packages, buildname = "autobuild", phases = [])
|
|
243
312
|
if Autobuild.mail[:to]
|
|
244
313
|
if !Autobuild::HAS_RMAIL
|
|
245
314
|
Autobuild.warn "RMail is not available. Mail notification is disabled"
|
|
@@ -261,13 +330,16 @@ module Autobuild
|
|
|
261
330
|
end
|
|
262
331
|
end
|
|
263
332
|
|
|
264
|
-
if
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
333
|
+
if phases.empty?
|
|
334
|
+
if Autobuild.only_doc
|
|
335
|
+
phases = ['doc']
|
|
336
|
+
else
|
|
337
|
+
phases = ['import']
|
|
338
|
+
phases += ['prepare', 'build'] if Autobuild.do_build
|
|
339
|
+
phases << 'doc' if Autobuild.do_doc
|
|
340
|
+
end
|
|
270
341
|
end
|
|
342
|
+
|
|
271
343
|
phases.each do |phase|
|
|
272
344
|
# We create a dummy task listing what needs to be done, and then we
|
|
273
345
|
# call it
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
require 'pathname'
|
|
2
|
-
require 'autobuild/timestamps'
|
|
3
|
-
require 'autobuild/environment'
|
|
4
|
-
require 'autobuild/package'
|
|
5
|
-
require 'autobuild/subcommand'
|
|
6
|
-
require 'shellwords'
|
|
7
|
-
|
|
8
1
|
module Autobuild
|
|
9
2
|
# Base class for packages that require a configuration + build step.
|
|
10
3
|
#
|
|
@@ -414,10 +414,9 @@ module Autobuild
|
|
|
414
414
|
end
|
|
415
415
|
|
|
416
416
|
require 'rbconfig'
|
|
417
|
-
|
|
418
|
-
candidates = %w{rubylibdir archdir sitelibdir sitearchdir vendorlibdir vendorarchdir}.
|
|
417
|
+
%w{rubylibdir archdir sitelibdir sitearchdir vendorlibdir vendorarchdir}.
|
|
419
418
|
map { |key| RbConfig::CONFIG[key] }.
|
|
420
|
-
map { |path| path.gsub(/.*lib(?:32|64)
|
|
419
|
+
map { |path| path.gsub(/.*lib(?:32|64)?\//, '\\1') }.
|
|
421
420
|
each do |subdir|
|
|
422
421
|
if File.directory?("#{newprefix}/lib/#{subdir}")
|
|
423
422
|
env_add_path("RUBYLIB", "#{newprefix}/lib/#{subdir}")
|
|
@@ -32,6 +32,30 @@ module Autobuild
|
|
|
32
32
|
# Known URI schemes for +url+
|
|
33
33
|
VALID_URI_SCHEMES = [ 'file', 'http', 'https', 'ftp' ]
|
|
34
34
|
|
|
35
|
+
class << self
|
|
36
|
+
# The directory in which downloaded files are saved
|
|
37
|
+
#
|
|
38
|
+
# It defaults, by order of priority, to the archives/ subdirectory
|
|
39
|
+
# of the environment variable AUTOBUILD_CACHE_DIR (if set), to the
|
|
40
|
+
# AUTOBUILD_ARCHIVES_CACHE_DIR (if set) environment variable and to
|
|
41
|
+
# #{prefix}/cache
|
|
42
|
+
def cachedir
|
|
43
|
+
if @cachedir then @cachedir
|
|
44
|
+
elsif dir = ENV['AUTOBUILD_ARCHIVES_CACHE_DIR']
|
|
45
|
+
@cachedir = File.expand_path(dir)
|
|
46
|
+
elsif dir = ENV['AUTOBUILD_CACHE_DIR']
|
|
47
|
+
@cachedir = File.join(File.expand_path(dir), 'archives')
|
|
48
|
+
else
|
|
49
|
+
@cachedir = "#{Autobuild.prefix}/cache"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Sets the directory in which files get cached
|
|
54
|
+
attr_writer :cachedir
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
@cachedir = nil
|
|
58
|
+
|
|
35
59
|
# Returns the unpack mode from the file name
|
|
36
60
|
def self.filename_to_mode(filename)
|
|
37
61
|
case filename
|
|
@@ -112,7 +136,7 @@ module Autobuild
|
|
|
112
136
|
size = File.stat(@url.path).size
|
|
113
137
|
mtime = File.stat(@url.path).mtime
|
|
114
138
|
else
|
|
115
|
-
open @url, :content_length_proc => lambda { |
|
|
139
|
+
open @url, :content_length_proc => lambda { |v| size = v } do |file|
|
|
116
140
|
mtime = file.last_modified
|
|
117
141
|
end
|
|
118
142
|
end
|
|
@@ -163,7 +187,9 @@ module Autobuild
|
|
|
163
187
|
# The unpack mode. One of Zip, Bzip, Gzip or Plain
|
|
164
188
|
attr_reader :mode
|
|
165
189
|
# The directory in which remote files are cached
|
|
166
|
-
|
|
190
|
+
#
|
|
191
|
+
# Defaults to ArchiveImporter.cachedir
|
|
192
|
+
attr_accessor :cachedir
|
|
167
193
|
# The directory contained in the tar file
|
|
168
194
|
#
|
|
169
195
|
# DEPRECATED use #archive_dir instead
|
|
@@ -192,7 +218,7 @@ module Autobuild
|
|
|
192
218
|
if !@options.has_key?(:update_cached_file)
|
|
193
219
|
@options[:update_cached_file] = false
|
|
194
220
|
end
|
|
195
|
-
@options[:cachedir]
|
|
221
|
+
@cachedir = @options[:cachedir] || ArchiveImporter.cachedir
|
|
196
222
|
|
|
197
223
|
relocate(url)
|
|
198
224
|
end
|
|
@@ -214,7 +240,11 @@ module Autobuild
|
|
|
214
240
|
end
|
|
215
241
|
end
|
|
216
242
|
|
|
217
|
-
def update(package) # :nodoc:
|
|
243
|
+
def update(package,only_local = false) # :nodoc:
|
|
244
|
+
if only_local
|
|
245
|
+
Autobuild.warn "The importer #{self.class} does not support local updates, skipping #{self}"
|
|
246
|
+
return
|
|
247
|
+
end
|
|
218
248
|
needs_update = update_cache(package)
|
|
219
249
|
|
|
220
250
|
if !File.file?(checkout_digest_stamp(package))
|
data/lib/autobuild/import/cvs.rb
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
require 'autobuild/config'
|
|
2
|
-
require 'autobuild/subcommand'
|
|
3
|
-
require 'autobuild/importer'
|
|
4
|
-
|
|
5
1
|
module Autobuild
|
|
6
2
|
class CVSImporter < Importer
|
|
7
3
|
# Creates a new importer which gets the module +name+ from the
|
|
@@ -38,7 +34,11 @@ module Autobuild
|
|
|
38
34
|
|
|
39
35
|
private
|
|
40
36
|
|
|
41
|
-
def update(package) # :nodoc:
|
|
37
|
+
def update(package,only_local=false) # :nodoc:
|
|
38
|
+
if only_local
|
|
39
|
+
Autobuild.warn "The importer #{self.class} does not support local updates, skipping #{self}"
|
|
40
|
+
return
|
|
41
|
+
end
|
|
42
42
|
Dir.chdir(package.srcdir) do
|
|
43
43
|
if !File.exists?("#{package.srcdir}/CVS/Root")
|
|
44
44
|
raise ConfigException.new(package, 'import'), "#{package.srcdir} is not a CVS working copy"
|
|
@@ -22,7 +22,11 @@ module Autobuild
|
|
|
22
22
|
|
|
23
23
|
private
|
|
24
24
|
|
|
25
|
-
def update(package) # :nodoc:
|
|
25
|
+
def update(package,only_local=false) # :nodoc:
|
|
26
|
+
if only_local
|
|
27
|
+
Autobuild.warn "The importer #{self.class} does not support local updates, skipping #{self}"
|
|
28
|
+
return
|
|
29
|
+
end
|
|
26
30
|
if !File.directory?( File.join(package.srcdir, '_darcs') )
|
|
27
31
|
raise ConfigException.new(package, 'import'), "#{package.srcdir} is not a Darcs repository"
|
|
28
32
|
end
|
data/lib/autobuild/import/git.rb
CHANGED
|
@@ -5,6 +5,36 @@ require 'utilrb/kernel/options'
|
|
|
5
5
|
|
|
6
6
|
module Autobuild
|
|
7
7
|
class Git < Importer
|
|
8
|
+
class << self
|
|
9
|
+
# Sets the default alternates path used by all Git importers
|
|
10
|
+
#
|
|
11
|
+
# Setting it explicitly overrides any value we get from the
|
|
12
|
+
# AUTOBUILD_CACHE_DIR and AUTOBUILD_GIT_CACHE_DIR environment
|
|
13
|
+
# variables.
|
|
14
|
+
#
|
|
15
|
+
# @see default_alternates
|
|
16
|
+
attr_writer :default_alternates
|
|
17
|
+
|
|
18
|
+
# A default list of repositories that should be used as reference
|
|
19
|
+
# repositories for all Git importers
|
|
20
|
+
#
|
|
21
|
+
# It is initialized (by order of priority) using the
|
|
22
|
+
# AUTOBUILD_GIT_CACHE_DIR and AUTOBUILD_CACHE_DIR environment
|
|
23
|
+
# variables
|
|
24
|
+
#
|
|
25
|
+
# @return [Array]
|
|
26
|
+
# @see default_alternates=, Git#alternates
|
|
27
|
+
def default_alternates
|
|
28
|
+
if @default_alternates then @default_alternates
|
|
29
|
+
elsif cache_dir = ENV['AUTOBUILD_GIT_CACHE_DIR']
|
|
30
|
+
@default_alternates = cache_dir.split(':').map { |path| File.expand_path(path) }
|
|
31
|
+
elsif cache_dir = ENV['AUTOBUILD_CACHE_DIR']
|
|
32
|
+
@default_alternates = cache_dir.split(':').map { |path| File.join(File.expand_path(path), 'git') }
|
|
33
|
+
else Array.new
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
8
38
|
# Creates an importer which tracks the given repository
|
|
9
39
|
# and branch. +source+ is [repository, branch]
|
|
10
40
|
#
|
|
@@ -14,6 +44,7 @@ module Autobuild
|
|
|
14
44
|
# Autobuild.programs['git'] = 'my_git_tool'
|
|
15
45
|
def initialize(repository, branch = nil, options = {})
|
|
16
46
|
@repository = repository.to_str
|
|
47
|
+
@alternates = Git.default_alternates.dup
|
|
17
48
|
|
|
18
49
|
if branch.respond_to?(:to_hash)
|
|
19
50
|
options = branch.to_hash
|
|
@@ -28,11 +59,12 @@ module Autobuild
|
|
|
28
59
|
Autobuild.warn " Autobuild.git 'git://gitorious.org/rock/buildconf.git', :branch => 'master'"
|
|
29
60
|
end
|
|
30
61
|
|
|
31
|
-
gitopts, common = Kernel.filter_options options, :push_to => nil, :branch => nil, :tag => nil, :commit => nil
|
|
62
|
+
gitopts, common = Kernel.filter_options options, :push_to => nil, :branch => nil, :tag => nil, :commit => nil, :with_submodules => false
|
|
32
63
|
if gitopts[:branch] && branch
|
|
33
64
|
raise ConfigException, "git branch specified with both the option hash and the explicit parameter"
|
|
34
65
|
end
|
|
35
66
|
@push_to = gitopts[:push_to]
|
|
67
|
+
@with_submodules = gitopts[:with_submodules]
|
|
36
68
|
branch = gitopts[:branch] || branch
|
|
37
69
|
tag = gitopts[:tag]
|
|
38
70
|
commit = gitopts[:commit]
|
|
@@ -40,6 +72,7 @@ module Autobuild
|
|
|
40
72
|
@branch = branch || 'master'
|
|
41
73
|
@tag = tag
|
|
42
74
|
@commit = commit
|
|
75
|
+
@remote_name = 'autobuild'
|
|
43
76
|
super(common)
|
|
44
77
|
end
|
|
45
78
|
|
|
@@ -50,6 +83,11 @@ module Autobuild
|
|
|
50
83
|
"git:#{repository}"
|
|
51
84
|
end
|
|
52
85
|
|
|
86
|
+
# The name of the remote that should be set up by the importer
|
|
87
|
+
#
|
|
88
|
+
# Defaults to 'autobuild'
|
|
89
|
+
attr_accessor :remote_name
|
|
90
|
+
|
|
53
91
|
# The remote repository URL.
|
|
54
92
|
#
|
|
55
93
|
# See also #push_to
|
|
@@ -67,6 +105,11 @@ module Autobuild
|
|
|
67
105
|
# Defaults to #branch
|
|
68
106
|
attr_writer :remote_branch
|
|
69
107
|
|
|
108
|
+
# Set to true if checkout should be done with submodules
|
|
109
|
+
#
|
|
110
|
+
# Defaults to #false
|
|
111
|
+
attr_writer :with_submodules
|
|
112
|
+
|
|
70
113
|
# The branch this importer is tracking
|
|
71
114
|
#
|
|
72
115
|
# If set, both commit and tag have to be nil.
|
|
@@ -77,6 +120,24 @@ module Autobuild
|
|
|
77
120
|
# If not set, it defaults to #branch
|
|
78
121
|
attr_writer :local_branch
|
|
79
122
|
|
|
123
|
+
# A list of local (same-host) repositories that will be used instead of
|
|
124
|
+
# the remote one when possible. It has one major issue (see below), so
|
|
125
|
+
# use at your own risk.
|
|
126
|
+
#
|
|
127
|
+
# The paths must point to the git directory, so either the .git
|
|
128
|
+
# directory in a checked out git repository, or the repository itself in
|
|
129
|
+
# a bare repository.
|
|
130
|
+
#
|
|
131
|
+
# A default reference repository can be given through the
|
|
132
|
+
# AUTOBUILD_GIT_CACHE environment variable.
|
|
133
|
+
#
|
|
134
|
+
# Note that it has the major caveat that if objects disappear from the
|
|
135
|
+
# reference repository, the current one will be broken. See the git
|
|
136
|
+
# documentation for more information.
|
|
137
|
+
#
|
|
138
|
+
# @return [Array<String>]
|
|
139
|
+
attr_accessor :alternates
|
|
140
|
+
|
|
80
141
|
# The branch that should be used on the local clone
|
|
81
142
|
#
|
|
82
143
|
# Defaults to #branch
|
|
@@ -106,6 +167,10 @@ module Autobuild
|
|
|
106
167
|
# a fast-forward
|
|
107
168
|
def merge?; !!@merge end
|
|
108
169
|
|
|
170
|
+
#Return true if the git checkout should be done with submodules
|
|
171
|
+
#detaul it false
|
|
172
|
+
def with_submodules?; !!@with_submodules end
|
|
173
|
+
|
|
109
174
|
# Set the merge flag. See #merge?
|
|
110
175
|
def merge=(flag); @merge = flag end
|
|
111
176
|
|
|
@@ -151,70 +216,73 @@ module Autobuild
|
|
|
151
216
|
end
|
|
152
217
|
end
|
|
153
218
|
|
|
219
|
+
def update_cache(package, cache_dir, phase)
|
|
220
|
+
remote_name = package.name.gsub(/[^\w]/, '_')
|
|
221
|
+
Subprocess.run(*git, "remote.#{remote_name}.url", repository)
|
|
222
|
+
Subprocess.run(*git, "remote.#{remote_name}.fetch", "+refs/heads/*:refs/remotes/#{remote_name}/*")
|
|
223
|
+
Subprocess.run(*git, 'fetch', '--tags', remote_name)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Updates the git repository's configuration for the target remote
|
|
227
|
+
def update_remotes_configuration(package, phase)
|
|
228
|
+
git = [package, phase, Autobuild.tool(:git), '--git-dir', File.join(package.importdir, '.git'), 'config', '--replace-all']
|
|
229
|
+
Subprocess.run(*git, "remote.#{remote_name}.url", repository)
|
|
230
|
+
if push_to
|
|
231
|
+
Subprocess.run(*git, "remote.#{remote_name}.pushurl", push_to)
|
|
232
|
+
end
|
|
233
|
+
Subprocess.run(*git, "remote.#{remote_name}.fetch", "+refs/heads/*:refs/remotes/#{remote_name}/*")
|
|
234
|
+
|
|
235
|
+
if remote_branch && local_branch
|
|
236
|
+
Subprocess.run(*git, "remote.#{remote_name}.push", "refs/heads/#{local_branch}:refs/heads/#{remote_branch}")
|
|
237
|
+
else
|
|
238
|
+
Subprocess.run(*git, "remote.#{remote_name}.push", "refs/heads/*:refs/heads/*")
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
if local_branch
|
|
242
|
+
Subprocess.run(*git, "branch.#{local_branch}.remote", remote_name)
|
|
243
|
+
Subprocess.run(*git, "branch.#{local_branch}.merge", "refs/heads/#{local_branch}")
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
154
247
|
# Fetches updates from the remote repository. Returns the remote commit
|
|
155
248
|
# ID on success, nil on failure. Expects the current directory to be the
|
|
156
249
|
# package's source directory.
|
|
157
250
|
def fetch_remote(package)
|
|
158
251
|
validate_importdir(package)
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
"--replace-all", "remote.autobuild.fetch", "+refs/heads/*:refs/remotes/autobuild/*")
|
|
184
|
-
|
|
185
|
-
if remote_branch && local_branch
|
|
186
|
-
Subprocess.run(package, :import, Autobuild.tool('git'), 'config',
|
|
187
|
-
"--replace-all", "remote.autobuild.push", "refs/heads/#{local_branch}:refs/heads/#{remote_branch}")
|
|
188
|
-
else
|
|
189
|
-
Subprocess.run(package, :import, Autobuild.tool('git'), 'config',
|
|
190
|
-
"--replace-all", "remote.autobuild.push", "refs/heads/*:refs/heads/*")
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
if local_branch
|
|
194
|
-
Subprocess.run(package, :import, Autobuild.tool('git'), 'config',
|
|
195
|
-
"--replace-all", "branch.#{local_branch}.remote", "autobuild")
|
|
196
|
-
Subprocess.run(package, :import, Autobuild.tool('git'), 'config',
|
|
197
|
-
"--replace-all", "branch.#{local_branch}.merge", "refs/heads/#{local_branch}")
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
# Now get the actual commit ID from the FETCH_HEAD file, and
|
|
201
|
-
# return it
|
|
202
|
-
commit_id = if File.readable?( File.join('.git', 'FETCH_HEAD') )
|
|
203
|
-
fetch_commit = File.readlines( File.join('.git', 'FETCH_HEAD') ).
|
|
204
|
-
delete_if { |l| l =~ /not-for-merge/ }
|
|
205
|
-
if !fetch_commit.empty?
|
|
206
|
-
fetch_commit.first.split(/\s+/).first
|
|
207
|
-
end
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
# Update the remote tag if needs be
|
|
211
|
-
if branch && commit_id
|
|
212
|
-
Subprocess.run(package, :import, Autobuild.tool('git'), 'update-ref',
|
|
213
|
-
"-m", "updated by autobuild", "refs/remotes/autobuild/#{remote_branch}", commit_id)
|
|
252
|
+
git = [package, :import, Autobuild.tool('git'), '--git-dir', File.join(package.importdir, '.git')]
|
|
253
|
+
|
|
254
|
+
# If we are checking out a specific commit, we don't know which
|
|
255
|
+
# branch to refer to in git fetch. So, we have to set up the
|
|
256
|
+
# remotes and call git fetch directly (so that all branches get
|
|
257
|
+
# fetch)
|
|
258
|
+
#
|
|
259
|
+
# Otherwise, do git fetch now
|
|
260
|
+
#
|
|
261
|
+
# Doing it now is better as it makes sure that we replace the
|
|
262
|
+
# configuration parameters only if the repository and branch are
|
|
263
|
+
# OK (i.e. we keep old working configuration instead)
|
|
264
|
+
refspec = [branch || tag].compact
|
|
265
|
+
Subprocess.run(*git, 'fetch', '--tags', repository, *refspec)
|
|
266
|
+
|
|
267
|
+
update_remotes_configuration(package, :import)
|
|
268
|
+
|
|
269
|
+
# Now get the actual commit ID from the FETCH_HEAD file, and
|
|
270
|
+
# return it
|
|
271
|
+
commit_id = if File.readable?( File.join(package.importdir, '.git', 'FETCH_HEAD') )
|
|
272
|
+
fetch_commit = File.readlines( File.join(package.importdir, '.git', 'FETCH_HEAD') ).
|
|
273
|
+
delete_if { |l| l =~ /not-for-merge/ }
|
|
274
|
+
if !fetch_commit.empty?
|
|
275
|
+
fetch_commit.first.split(/\s+/).first
|
|
214
276
|
end
|
|
277
|
+
end
|
|
215
278
|
|
|
216
|
-
|
|
279
|
+
# Update the remote tag if needs be
|
|
280
|
+
if branch && commit_id
|
|
281
|
+
Subprocess.run(*git, 'update-ref',
|
|
282
|
+
"-m", "updated by autobuild", "refs/remotes/#{remote_name}/#{remote_branch}", commit_id)
|
|
217
283
|
end
|
|
284
|
+
|
|
285
|
+
commit_id
|
|
218
286
|
end
|
|
219
287
|
|
|
220
288
|
# Returns a Importer::Status object that represents the status of this
|
|
@@ -224,7 +292,7 @@ module Autobuild
|
|
|
224
292
|
validate_importdir(package)
|
|
225
293
|
remote_commit = nil
|
|
226
294
|
if only_local
|
|
227
|
-
remote_commit = `git show-ref -s refs/remotes
|
|
295
|
+
remote_commit = `git show-ref -s refs/remotes/#{remote_name}/#{remote_branch}`.chomp
|
|
228
296
|
else
|
|
229
297
|
remote_commit =
|
|
230
298
|
begin fetch_remote(package)
|
|
@@ -355,10 +423,48 @@ module Autobuild
|
|
|
355
423
|
Status.new(status, fetch_commit, head_commit, common_commit)
|
|
356
424
|
end
|
|
357
425
|
|
|
358
|
-
|
|
426
|
+
# Updates the git alternates file in the already checked out package to
|
|
427
|
+
# match {#alternates}
|
|
428
|
+
#
|
|
429
|
+
# @param [Package] package the already checked-out package
|
|
430
|
+
# @return [void]
|
|
431
|
+
def update_alternates(package)
|
|
432
|
+
alternates_path = File.join(package.importdir, '.git', 'objects', 'info', 'alternates')
|
|
433
|
+
current_alternates =
|
|
434
|
+
if File.file?(alternates_path)
|
|
435
|
+
File.readlines(alternates_path).map(&:strip).find_all { |l| !l.empty? }
|
|
436
|
+
else Array.new
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
alternates = self.alternates.map do |path|
|
|
440
|
+
File.join(path, 'objects')
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
if current_alternates.sort != alternates.sort
|
|
444
|
+
# Warn that something is fishy, but assume that the user knows
|
|
445
|
+
# what he is doing
|
|
446
|
+
package.warn "%s: the list of git alternates listed in the repository differs from the one set up in autobuild."
|
|
447
|
+
package.warn "%s: I will update, but that is dangerous"
|
|
448
|
+
package.warn "%s: using git alternates is for advanced users only, who know git very well."
|
|
449
|
+
package.warn "%s: Don't complain if something breaks"
|
|
450
|
+
end
|
|
451
|
+
if alternates.empty?
|
|
452
|
+
FileUtils.rm_f alternates_path
|
|
453
|
+
else
|
|
454
|
+
File.open(alternates_path, 'w') do |io|
|
|
455
|
+
io.write alternates.join("\n")
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
def update(package,only_local = false)
|
|
359
461
|
validate_importdir(package)
|
|
462
|
+
update_alternates(package)
|
|
360
463
|
Dir.chdir(package.importdir) do
|
|
361
|
-
|
|
464
|
+
#Checking if we should only merge our repro to remotes/HEAD without updateing from the remote side...
|
|
465
|
+
if !only_local
|
|
466
|
+
fetch_commit = fetch_remote(package)
|
|
467
|
+
end
|
|
362
468
|
|
|
363
469
|
# If we are tracking a commit/tag, just check it out and return
|
|
364
470
|
if commit || tag
|
|
@@ -429,17 +535,25 @@ module Autobuild
|
|
|
429
535
|
FileUtils.mkdir_p base_dir
|
|
430
536
|
end
|
|
431
537
|
|
|
538
|
+
clone_options = ['-o', remote_name]
|
|
539
|
+
|
|
540
|
+
if with_submodules?
|
|
541
|
+
clone_options << '--recurse-submodules'
|
|
542
|
+
end
|
|
543
|
+
alternates.each do |path|
|
|
544
|
+
clone_options << '--reference' << path
|
|
545
|
+
end
|
|
432
546
|
Subprocess.run(package, :import,
|
|
433
|
-
Autobuild.tool('git'), 'clone',
|
|
547
|
+
Autobuild.tool('git'), 'clone', *clone_options, repository, package.importdir)
|
|
434
548
|
|
|
435
549
|
Dir.chdir(package.importdir) do
|
|
436
550
|
if push_to
|
|
437
551
|
Subprocess.run(package, :import, Autobuild.tool('git'), 'config',
|
|
438
|
-
"--replace-all", "remote.
|
|
552
|
+
"--replace-all", "remote.#{remote_name}.pushurl", push_to)
|
|
439
553
|
end
|
|
440
554
|
if local_branch && remote_branch
|
|
441
555
|
Subprocess.run(package, :import, Autobuild.tool('git'), 'config',
|
|
442
|
-
"--replace-all", "remote.
|
|
556
|
+
"--replace-all", "remote.#{remote_name}.push", "refs/heads/#{local_branch}:refs/heads/#{remote_branch}")
|
|
443
557
|
end
|
|
444
558
|
|
|
445
559
|
# If we are tracking a commit/tag, just check it out
|
|
@@ -453,10 +567,10 @@ module Autobuild
|
|
|
453
567
|
current_branch = `git symbolic-ref HEAD`.chomp
|
|
454
568
|
if current_branch == "refs/heads/#{local_branch}"
|
|
455
569
|
Subprocess.run(package, :import, Autobuild.tool('git'),
|
|
456
|
-
'reset', '--hard', "
|
|
570
|
+
'reset', '--hard', "#{remote_name}/#{branch}")
|
|
457
571
|
else
|
|
458
572
|
Subprocess.run(package, :import, Autobuild.tool('git'),
|
|
459
|
-
'checkout', '-b', local_branch, "
|
|
573
|
+
'checkout', '-b', local_branch, "#{remote_name}/#{branch}")
|
|
460
574
|
end
|
|
461
575
|
end
|
|
462
576
|
end
|
|
@@ -466,6 +580,38 @@ module Autobuild
|
|
|
466
580
|
def relocate(repository)
|
|
467
581
|
@repository = repository
|
|
468
582
|
end
|
|
583
|
+
|
|
584
|
+
# Tests whether the given directory is a git repository
|
|
585
|
+
def self.can_handle?(path)
|
|
586
|
+
File.directory?(File.join(path, '.git'))
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
# Returns a hash that represents the configuration of a git importer
|
|
590
|
+
# based on the information contained in the git configuration
|
|
591
|
+
#
|
|
592
|
+
# @raise [ArgumentError] if the path does not point to a git repository
|
|
593
|
+
def self.vcs_definition_for(path)
|
|
594
|
+
if !can_handle?(path)
|
|
595
|
+
raise ArgumentError, "#{path} is not a git repository"
|
|
596
|
+
end
|
|
597
|
+
|
|
598
|
+
Dir.chdir(path) do
|
|
599
|
+
vars = `git config -l`.
|
|
600
|
+
split("\n").
|
|
601
|
+
inject(Hash.new) do |h, line|
|
|
602
|
+
k, v = line.strip.split('=', 2)
|
|
603
|
+
h[k] = v
|
|
604
|
+
h
|
|
605
|
+
end
|
|
606
|
+
url = vars["remote.#{remote_name}.url"] ||
|
|
607
|
+
vars['remote.origin.url']
|
|
608
|
+
if url
|
|
609
|
+
return Hash[:type => :git, :url => url]
|
|
610
|
+
else
|
|
611
|
+
return Hash[:type => :git]
|
|
612
|
+
end
|
|
613
|
+
end
|
|
614
|
+
end
|
|
469
615
|
end
|
|
470
616
|
|
|
471
617
|
# Creates a git importer which gets the source for the given repository and branch
|