autobuild 1.7.10 → 1.7.11.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|